Merge "audio service: add config option for fixed volume" into jb-mr2-dev
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7a6a1e9..cc50d8a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1043,4 +1043,9 @@
 
     <!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
     <string name="config_appsAuthorizedForSharedAccounts"></string>
+
+    <!-- Flag indicating that the media framework should not allow changes or mute on any
+         stream or master volumes. -->
+    <bool name="config_useFixedVolume">false</bool>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 80e77dd..81baaf8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -277,6 +277,7 @@
   <java-symbol type="bool" name="config_camera_sound_forced" />
   <java-symbol type="bool" name="config_dontPreferApn" />
   <java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
+  <java-symbol type="bool" name="config_useFixedVolume" />
 
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 47c70f8..18f3b1e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -257,6 +257,8 @@
     };
     private int[] mStreamVolumeAlias;
 
+    private final boolean mUseFixedVolume;
+
     // stream names used by dumpStreamStates()
     private final String[] STREAM_NAMES = new String[] {
             "STREAM_VOICE_CALL",
@@ -487,6 +489,9 @@
         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
 
+        mUseFixedVolume = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useFixedVolume);
+
         readPersistedSettings();
         mSettingsObserver = new SettingsObserver();
         updateStreamVolumeAlias(false /*updateVolumes*/);
@@ -678,6 +683,9 @@
         if (ringerMode != ringerModeFromSettings) {
             Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
         }
+        if (mUseFixedVolume) {
+            ringerMode = AudioManager.RINGER_MODE_NORMAL;
+        }
         synchronized(mSettingsLock) {
             mRingerMode = ringerMode;
 
@@ -736,6 +744,10 @@
 
         boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
                                                   0, UserHandle.USER_CURRENT) == 1;
+        if (mUseFixedVolume) {
+            masterMute = false;
+            AudioSystem.setMasterVolume(1.0f);
+        }
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
@@ -806,6 +818,9 @@
 
     /** @see AudioManager#adjustStreamVolume(int, int, int) */
     public void adjustStreamVolume(int streamType, int direction, int flags) {
+        if (mUseFixedVolume) {
+            return;
+        }
         if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction);
 
         ensureValidDirection(direction);
@@ -918,6 +933,9 @@
 
     /** @see AudioManager#adjustMasterVolume(int, int) */
     public void adjustMasterVolume(int steps, int flags) {
+        if (mUseFixedVolume) {
+            return;
+        }
         ensureValidSteps(steps);
         int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
         int delta = 0;
@@ -972,6 +990,10 @@
 
     /** @see AudioManager#setStreamVolume(int, int, int) */
     public void setStreamVolume(int streamType, int index, int flags) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         ensureValidStreamType(streamType);
         VolumeStreamState streamState = mStreamStates[mStreamVolumeAlias[streamType]];
 
@@ -1214,6 +1236,10 @@
 
     /** @see AudioManager#setStreamSolo(int, boolean) */
     public void setStreamSolo(int streamType, boolean state, IBinder cb) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         for (int stream = 0; stream < mStreamStates.length; stream++) {
             if (!isStreamAffectedByMute(stream) || stream == streamType) continue;
             // Bring back last audible volume
@@ -1223,6 +1249,10 @@
 
     /** @see AudioManager#setStreamMute(int, boolean) */
     public void setStreamMute(int streamType, boolean state, IBinder cb) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         if (isStreamAffectedByMute(streamType)) {
             mStreamStates[streamType].mute(cb, state);
         }
@@ -1235,6 +1265,10 @@
 
     /** @see AudioManager#setMasterMute(boolean, int) */
     public void setMasterMute(boolean state, int flags, IBinder cb) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         if (state != AudioSystem.getMasterMute()) {
             AudioSystem.setMasterMute(state);
             // Post a persist master volume msg
@@ -1268,6 +1302,10 @@
     }
 
     public void setMasterVolume(int volume, int flags) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         if (volume < 0) {
             volume = 0;
         } else if (volume > MAX_MASTER_VOLUME) {
@@ -1339,6 +1377,10 @@
 
     /** @see AudioManager#setRingerMode(int) */
     public void setRingerMode(int ringerMode) {
+        if (mUseFixedVolume) {
+            return;
+        }
+
         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
             ringerMode = AudioManager.RINGER_MODE_SILENT;
         }
@@ -1398,6 +1440,10 @@
     }
 
     private void restoreMasterVolume() {
+        if (mUseFixedVolume) {
+            AudioSystem.setMasterVolume(1.0f);
+            return;
+        }
         if (mUseMasterVolume) {
             float volume = Settings.System.getFloatForUser(mContentResolver,
                     Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
@@ -1951,8 +1997,8 @@
                 streamState.readSettings();
 
                 // unmute stream that was muted but is not affect by mute anymore
-                if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType) &&
-                        !isStreamMutedByRingerMode(streamType)) {
+                if (streamState.muteCount() != 0 && ((!isStreamAffectedByMute(streamType) &&
+                        !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
                     int size = streamState.mDeathHandlers.size();
                     for (int i = 0; i < size; i++) {
                         streamState.mDeathHandlers.get(i).mMuteCount = 1;
@@ -2833,8 +2879,12 @@
         }
 
         public synchronized void readSettings() {
-            int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
-
+            // force maximum volume on all streams if fixed volume property is set
+            if (mUseFixedVolume) {
+                mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
+                mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
+                return;
+            }
             // do not read system stream volume from settings: this stream is always aliased
             // to another stream type and its volume is never persisted. Values in settings can
             // only be stale values
@@ -2855,6 +2905,8 @@
                 return;
             }
 
+            int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
+
             for (int i = 0; remainingDevices != 0; i++) {
                 int device = (1 << i);
                 if ((device & remainingDevices) == 0) {
@@ -2972,7 +3024,7 @@
                     index = mIndexMax;
                 }
             }
-            mIndex.put(device, getValidIndex(index));
+            mIndex.put(device, index);
 
             if (oldIndex != index) {
                 if (lastAudible) {
@@ -3106,7 +3158,7 @@
         private int getValidIndex(int index) {
             if (index < 0) {
                 return 0;
-            } else if (index > mIndexMax) {
+            } else if (mUseFixedVolume || index > mIndexMax) {
                 return mIndexMax;
             }
 
@@ -3328,6 +3380,9 @@
         private void persistVolume(VolumeStreamState streamState,
                                    int persistType,
                                    int device) {
+            if (mUseFixedVolume) {
+                return;
+            }
             if ((persistType & PERSIST_CURRENT) != 0) {
                 System.putIntForUser(mContentResolver,
                           streamState.getSettingNameForDevice(false /* lastAudible */, device),
@@ -3343,6 +3398,9 @@
         }
 
         private void persistRingerMode(int ringerMode) {
+            if (mUseFixedVolume) {
+                return;
+            }
             Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
         }
 
@@ -3439,6 +3497,9 @@
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME:
+                    if (mUseFixedVolume) {
+                        return;
+                    }
                     Settings.System.putFloatForUser(mContentResolver,
                                                     Settings.System.VOLUME_MASTER,
                                                     (float)msg.arg1 / (float)1000.0,
@@ -3446,6 +3507,9 @@
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME_MUTE:
+                    if (mUseFixedVolume) {
+                        return;
+                    }
                     Settings.System.putIntForUser(mContentResolver,
                                                  Settings.System.VOLUME_MASTER_MUTE,
                                                  msg.arg1,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
index 7967ce7..e232338 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
@@ -42,6 +42,7 @@
     private final static int WAIT_FOR_LOOPER_TO_INITIALIZE_MS = 60000;  // 60s
     private int[] ringtoneMode = {AudioManager.RINGER_MODE_NORMAL,
              AudioManager.RINGER_MODE_SILENT, AudioManager.RINGER_MODE_VIBRATE};
+    private boolean mUseFixedVolume;
 
     public MediaAudioManagerTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -65,6 +66,10 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mUseFixedVolume = getActivity().getResources().getBoolean(
+                com.android.internal.R.bool.config_useFixedVolume);
+
         synchronized(mLooperLock) {
             initializeAudioManagerWithLooper();
             try {
@@ -91,10 +96,12 @@
 
      public boolean validateSetRingTone(int i) {
          int getRingtone = mAudioManager.getRingerMode();
-         if (i != getRingtone)
-             return false;
-         else
-             return true;
+
+         if (mUseFixedVolume) {
+             return (getRingtone == AudioManager.RINGER_MODE_NORMAL);
+         } else {
+             return (getRingtone == i);
+         }
      }
 
      // Test case 1: Simple test case to validate the set ringtone mode
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 761eb2d..a2ac8fe 100755
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -102,6 +102,7 @@
     private boolean mIsWaitingForEcmExit = false;
     private boolean mHasTelephony;
     private boolean mHasVibrator;
+    private final boolean mShowSilentToggle;
 
     /**
      * @param context everything needs a context :(
@@ -132,6 +133,9 @@
                 mAirplaneModeObserver);
         Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = vibrator != null && vibrator.hasVibrator();
+
+        mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useFixedVolume);
     }
 
     /**
@@ -309,7 +313,7 @@
         }
 
         // last: silent mode
-        if (SHOW_SILENT_TOGGLE) {
+        if (mShowSilentToggle) {
             mItems.add(mSilentModeAction);
         }
 
@@ -390,7 +394,7 @@
         mAirplaneModeOn.updateState(mAirplaneState);
         mAdapter.notifyDataSetChanged();
         mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        if (SHOW_SILENT_TOGGLE) {
+        if (mShowSilentToggle) {
             IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
             mContext.registerReceiver(mRingerModeReceiver, filter);
         }
@@ -407,7 +411,7 @@
 
     /** {@inheritDoc} */
     public void onDismiss(DialogInterface dialog) {
-        if (SHOW_SILENT_TOGGLE) {
+        if (mShowSilentToggle) {
             try {
                 mContext.unregisterReceiver(mRingerModeReceiver);
             } catch (IllegalArgumentException ie) {