Merge "Add plumbing for volume mute key."
diff --git a/api/current.xml b/api/current.xml
index ed9ed53..1e6fa92 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -196846,6 +196846,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_VOLUME_MUTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="164"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_VOLUME_UP"
  type="int"
  transient="false"
@@ -245598,7 +245609,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index 970d520..66c9ba1 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -92,6 +92,11 @@
                     mSeekBarVolumizer.changeVolumeBy(1);
                 }
                 return true;
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+                if (isdown) {
+                    mSeekBarVolumizer.muteVolume();
+                }
+                return true;
             default:
                 return false;
         }
@@ -225,6 +230,7 @@
     
         private int mLastProgress = -1;
         private SeekBar mSeekBar;
+        private int mVolumeBeforeMute = -1;
         
         private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
             @Override
@@ -336,6 +342,21 @@
                 sample();
             }
             postSetVolume(mSeekBar.getProgress());
+            mVolumeBeforeMute = -1;
+        }
+
+        public void muteVolume() {
+            if (mVolumeBeforeMute != -1) {
+                mSeekBar.setProgress(mVolumeBeforeMute);
+                sample();
+                postSetVolume(mVolumeBeforeMute);
+                mVolumeBeforeMute = -1;
+            } else {
+                mVolumeBeforeMute = mSeekBar.getProgress();
+                mSeekBar.setProgress(0);
+                stopSample();
+                postSetVolume(0);
+            }
         }
 
         public void onSaveInstanceState(VolumeStore volumeStore) {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 0e75682..04c331f 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -125,9 +125,11 @@
     /** Key code constant: Directional Pad Center key.
      * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_CENTER     = 23;
-    /** Key code constant: Volume Up key. */
+    /** Key code constant: Volume Up key.
+     * Adjusts the speaker volume up. */
     public static final int KEYCODE_VOLUME_UP       = 24;
-    /** Key code constant: Volume Down key. */
+    /** Key code constant: Volume Down key.
+     * Adjusts the speaker volume down. */
     public static final int KEYCODE_VOLUME_DOWN     = 25;
     /** Key code constant: Power key. */
     public static final int KEYCODE_POWER           = 26;
@@ -269,7 +271,8 @@
     public static final int KEYCODE_MEDIA_REWIND    = 89;
     /** Key code constant: Fast Forward media key. */
     public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
-    /** Key code constant: Mute key. */
+    /** Key code constant: Mute key.
+     * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
     public static final int KEYCODE_MUTE            = 91;
     /** Key code constant: Page Up key. */
     public static final int KEYCODE_PAGE_UP         = 92;
@@ -455,8 +458,13 @@
     public static final int KEYCODE_NUMPAD_LEFT_PAREN = 162;
     /** Key code constant: Numeric keypad ')' key. */
     public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163;
+    /** Key code constant: Volume Mute key.
+     * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
+     * This key should normally be implemented as a toggle such that the first press
+     * mutes the speaker and the second press restores the original volume. */
+    public static final int KEYCODE_VOLUME_MUTE     = 164;
 
-    private static final int LAST_KEYCODE           = KEYCODE_NUMPAD_RIGHT_PAREN;
+    private static final int LAST_KEYCODE           = KEYCODE_VOLUME_MUTE;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -640,6 +648,7 @@
         "KEYCODE_NUMPAD_EQUALS",
         "KEYCODE_NUMPAD_LEFT_PAREN",
         "KEYCODE_NUMPAD_RIGHT_PAREN",
+        "KEYCODE_VOLUME_MUTE",
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index be1234d..27a6ad3 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -442,7 +442,8 @@
             }
             return true;
         } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
-                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+                || keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
             // don't show the controls for volume adjustment
             return super.dispatchKeyEvent(event);
         } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 2be7bca..ec31dd4 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -515,6 +515,7 @@
         boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
                                      keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
                                      keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
+                                     keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
                                      keyCode != KeyEvent.KEYCODE_MENU &&
                                      keyCode != KeyEvent.KEYCODE_CALL &&
                                      keyCode != KeyEvent.KEYCODE_ENDCALL;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 79131ba..a2fa1a3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1145,27 +1145,28 @@
         <enum name="KEYCODE_F10" value="140" />
         <enum name="KEYCODE_F11" value="141" />
         <enum name="KEYCODE_F12" value="142" />
-        <enum name="NUM_LOCK" value="143" />
-        <enum name="NUMPAD_0" value="144" />
-        <enum name="NUMPAD_1" value="145" />
-        <enum name="NUMPAD_2" value="146" />
-        <enum name="NUMPAD_3" value="147" />
-        <enum name="NUMPAD_4" value="148" />
-        <enum name="NUMPAD_5" value="149" />
-        <enum name="NUMPAD_6" value="150" />
-        <enum name="NUMPAD_7" value="151" />
-        <enum name="NUMPAD_8" value="152" />
-        <enum name="NUMPAD_9" value="153" />
-        <enum name="NUMPAD_DIVIDE" value="154" />
-        <enum name="NUMPAD_MULTIPLY" value="155" />
-        <enum name="NUMPAD_SUBTRACT" value="156" />
-        <enum name="NUMPAD_ADD" value="157" />
-        <enum name="NUMPAD_DOT" value="158" />
-        <enum name="NUMPAD_COMMA" value="159" />
-        <enum name="NUMPAD_ENTER" value="160" />
-        <enum name="NUMPAD_EQUALS" value="161" />
-        <enum name="NUMPAD_LEFT_PAREN" value="162" />
-        <enum name="NUMPAD_RIGHT_PAREN" value="163" />
+        <enum name="KEYCODE_NUM_LOCK" value="143" />
+        <enum name="KEYCODE_NUMPAD_0" value="144" />
+        <enum name="KEYCODE_NUMPAD_1" value="145" />
+        <enum name="KEYCODE_NUMPAD_2" value="146" />
+        <enum name="KEYCODE_NUMPAD_3" value="147" />
+        <enum name="KEYCODE_NUMPAD_4" value="148" />
+        <enum name="KEYCODE_NUMPAD_5" value="149" />
+        <enum name="KEYCODE_NUMPAD_6" value="150" />
+        <enum name="KEYCODE_NUMPAD_7" value="151" />
+        <enum name="KEYCODE_NUMPAD_8" value="152" />
+        <enum name="KEYCODE_NUMPAD_9" value="153" />
+        <enum name="KEYCODE_NUMPAD_DIVIDE" value="154" />
+        <enum name="KEYCODE_NUMPAD_MULTIPLY" value="155" />
+        <enum name="KEYCODE_NUMPAD_SUBTRACT" value="156" />
+        <enum name="KEYCODE_NUMPAD_ADD" value="157" />
+        <enum name="KEYCODE_NUMPAD_DOT" value="158" />
+        <enum name="KEYCODE_NUMPAD_COMMA" value="159" />
+        <enum name="KEYCODE_NUMPAD_ENTER" value="160" />
+        <enum name="KEYCODE_NUMPAD_EQUALS" value="161" />
+        <enum name="KEYCODE_NUMPAD_LEFT_PAREN" value="162" />
+        <enum name="KEYCODE_NUMPAD_RIGHT_PAREN" value="163" />
+        <enum name="KEYCODE_VOLUME_MUTE" value="164" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 818397b..e98000d 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -132,7 +132,7 @@
 key 110   INSERT
 key 111   FORWARD_DEL
 # key 112 "KEY_MACRO"
-key 113   MUTE
+key 113   VOLUME_MUTE
 key 114   VOLUME_DOWN
 key 115   VOLUME_UP
 key 116   POWER             WAKE
diff --git a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
index 1298d53..eab78a0 100644
--- a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
+++ b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
@@ -83,9 +83,10 @@
 key 105   DPAD_LEFT
 key 106   DPAD_RIGHT
 key 107   MOVE_END
+key 108   DPAD_DOWN
 key 110   INSERT
 key 111   FORWARD_DEL
-key 113   MUTE
+key 113   VOLUME_MUTE
 key 114   VOLUME_DOWN
 key 115   VOLUME_UP
 key 125   MENU
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index ef2b6b3..73f5863 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -188,6 +188,7 @@
     { "NUMPAD_EQUALS", 161 },
     { "NUMPAD_LEFT_PAREN", 162 },
     { "NUMPAD_RIGHT_PAREN", 163 },
+    { "VOLUME_MUTE", 164 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 811edaf..944a79b 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -33,6 +33,7 @@
         case AKEYCODE_ENDCALL:
         case AKEYCODE_VOLUME_UP:
         case AKEYCODE_VOLUME_DOWN:
+        case AKEYCODE_VOLUME_MUTE:
         case AKEYCODE_POWER:
         case AKEYCODE_CAMERA:
         case AKEYCODE_HEADSETHOOK:
@@ -40,11 +41,14 @@
         case AKEYCODE_NOTIFICATION:
         case AKEYCODE_FOCUS:
         case AKEYCODE_SEARCH:
+        case AKEYCODE_MEDIA_PLAY:
+        case AKEYCODE_MEDIA_PAUSE:
         case AKEYCODE_MEDIA_PLAY_PAUSE:
         case AKEYCODE_MEDIA_STOP:
         case AKEYCODE_MEDIA_NEXT:
         case AKEYCODE_MEDIA_PREVIOUS:
         case AKEYCODE_MEDIA_REWIND:
+        case AKEYCODE_MEDIA_RECORD:
         case AKEYCODE_MEDIA_FAST_FORWARD:
         case AKEYCODE_MUTE:
             return true;
@@ -67,14 +71,18 @@
         case AKEYCODE_ENDCALL:
         case AKEYCODE_VOLUME_UP:
         case AKEYCODE_VOLUME_DOWN:
+        case AKEYCODE_VOLUME_MUTE:
         case AKEYCODE_MUTE:
         case AKEYCODE_POWER:
         case AKEYCODE_HEADSETHOOK:
+        case AKEYCODE_MEDIA_PLAY:
+        case AKEYCODE_MEDIA_PAUSE:
         case AKEYCODE_MEDIA_PLAY_PAUSE:
         case AKEYCODE_MEDIA_STOP:
         case AKEYCODE_MEDIA_NEXT:
         case AKEYCODE_MEDIA_PREVIOUS:
         case AKEYCODE_MEDIA_REWIND:
+        case AKEYCODE_MEDIA_RECORD:
         case AKEYCODE_MEDIA_FAST_FORWARD:
         case AKEYCODE_CAMERA:
         case AKEYCODE_FOCUS:
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 3fcf977..11142537 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -207,7 +207,7 @@
     AKEYCODE_NUMPAD_EQUALS   = 161,
     AKEYCODE_NUMPAD_LEFT_PAREN = 162,
     AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
-
+    AKEYCODE_VOLUME_MUTE     = 164,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 0f1aa4e..34dbace 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -170,7 +170,8 @@
                 }
 
                 case KeyEvent.KEYCODE_VOLUME_UP:
-                case KeyEvent.KEYCODE_VOLUME_DOWN: {
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                case KeyEvent.KEYCODE_VOLUME_MUTE: {
                     synchronized (this) {
                         if (mAudioManager == null) {
                             mAudioManager = (AudioManager) getContext().getSystemService(
@@ -179,6 +180,7 @@
                     }
                     // Volume buttons should only function for music.
                     if (mAudioManager.isMusicActive()) {
+                        // TODO: Actually handle MUTE.
                         mAudioManager.adjustStreamVolume(
                                     AudioManager.STREAM_MUSIC,
                                     keyCode == KeyEvent.KEYCODE_VOLUME_UP
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index c870503..42b73b9 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -786,6 +786,7 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
             case KeyEvent.KEYCODE_MUTE:
             case KeyEvent.KEYCODE_HEADSETHOOK:
             case KeyEvent.KEYCODE_MEDIA_PLAY:
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e944f9d..cd88821 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1230,7 +1230,8 @@
         
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
-            case KeyEvent.KEYCODE_VOLUME_DOWN: {
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 AudioManager audioManager = (AudioManager) getContext().getSystemService(
                         Context.AUDIO_SERVICE);
                 if (audioManager != null) {
@@ -1238,6 +1239,7 @@
                      * Adjust the volume in on key down since it is more
                      * responsive to the user.
                      */
+                    // TODO: Actually handle MUTE.
                     audioManager.adjustSuggestedStreamVolume(
                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
                                     ? AudioManager.ADJUST_RAISE
@@ -1405,7 +1407,8 @@
         
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
-            case KeyEvent.KEYCODE_VOLUME_DOWN: {
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 if (!event.isCanceled()) {
                     AudioManager audioManager = (AudioManager) getContext().getSystemService(
                             Context.AUDIO_SERVICE);
@@ -1414,6 +1417,7 @@
                          * Play a sound. This is done on key up since we don't want the
                          * sound to play when a user holds down volume down to mute.
                          */
+                        // TODO: Actually handle MUTE.
                         audioManager.adjustSuggestedStreamVolume(
                                 AudioManager.ADJUST_SAME,
                                 mVolumeControlStreamType,
@@ -1720,6 +1724,7 @@
              * cancel the sound
              */
             if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
+                    && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
                     && mVolumeKeyUpTime + VolumePanel.PLAY_SOUND_DELAY
                             > SystemClock.uptimeMillis()) {
                 /*
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e950ae5..af1bf59 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1877,6 +1877,7 @@
             // since audio is playing, we shouldn't have to hold a wake lock
             // during the call, but we do it as a precaution for the rare possibility
             // that the music stops right before we call this
+            // TODO: Actually handle MUTE.
             mBroadcastWakeLock.acquire();
             audioService.adjustStreamVolume(stream,
                 keycode == KeyEvent.KEYCODE_VOLUME_UP
@@ -1949,7 +1950,8 @@
         // Handle special keys.
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_DOWN:
-            case KeyEvent.KEYCODE_VOLUME_UP: {
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 if (down) {
                     ITelephony telephonyService = getTelephonyService();
                     if (telephonyService != null) {