diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 4fdcfa41e9bab..8c1ba05c78486 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -865,6 +865,24 @@ public class AudioManager { } } + /** + * Returns the minimum volume index for a particular stream. + * + * @param streamType The stream type whose minimum volume index is returned. + * @return The minimum valid volume index for the stream. + * @see #getStreamVolume(int) + * @hide + */ + public int getStreamMinVolume(int streamType) { + IAudioService service = getService(); + try { + return service.getStreamMinVolume(streamType); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in getStreamMinVolume", e); + return 0; + } + } + /** * Returns the current volume index for a particular stream. * diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 827cb13f8ee14..8e9621875f30d 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -59,6 +59,8 @@ interface IAudioService { int getStreamVolume(int streamType); + int getStreamMinVolume(int streamType); + int getStreamMaxVolume(int streamType); int getLastAudibleStreamVolume(int streamType); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java index 51adaacd72f82..d16b8181be18d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java @@ -253,6 +253,7 @@ public class VolumePanel extends Handler implements DemoMode { int iconRes; int iconMuteRes; int iconSuppressedRes; + int minVolume; } // Synchronize when accessing this @@ -558,6 +559,14 @@ public class VolumePanel extends Handler implements DemoMode { } } + private int getStreamMinVolume(int streamType) { + if (streamType == STREAM_REMOTE_MUSIC) { + return 0; + } else { + return mAudioManager.getStreamMinVolume(streamType); + } + } + private int getStreamMaxVolume(int streamType) { if (streamType == STREAM_REMOTE_MUSIC) { if (mStreamControls != null) { @@ -661,9 +670,8 @@ public class VolumePanel extends Handler implements DemoMode { } }); } - final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || - streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0; - sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne); + sc.minVolume = getStreamMinVolume(streamType); + sc.seekbarView.setMax(getStreamMaxVolume(streamType) - sc.minVolume); sc.seekbarView.setOnSeekBarChangeListener(mSeekListener); sc.seekbarView.setTag(sc); mStreamControls.put(streamType, sc); @@ -706,7 +714,7 @@ public class VolumePanel extends Handler implements DemoMode { if (progress < 0) { progress = getStreamVolume(sc.streamType); } - sc.seekbarView.setProgress(progress); + sc.seekbarView.setProgress(progress - sc.minVolume); if (isRinger) { mLastRingerProgress = progress; } @@ -1034,7 +1042,7 @@ public class VolumePanel extends Handler implements DemoMode { // get max volume for progress bar - int max = getStreamMaxVolume(streamType); + int max = getStreamMaxVolume(streamType) - getStreamMinVolume(streamType); StreamControl sc = mStreamControls.get(streamType); switch (streamType) { @@ -1061,17 +1069,6 @@ public class VolumePanel extends Handler implements DemoMode { break; } - case AudioManager.STREAM_VOICE_CALL: { - /* - * For in-call voice call volume, there is no inaudible volume. - * Rescale the UI control so the progress bar doesn't go all - * the way to zero and don't show the mute icon. - */ - index++; - max++; - break; - } - case AudioManager.STREAM_ALARM: { break; } @@ -1085,17 +1082,6 @@ public class VolumePanel extends Handler implements DemoMode { break; } - case AudioManager.STREAM_BLUETOOTH_SCO: { - /* - * For in-call voice call volume, there is no inaudible volume. - * Rescale the UI control so the progress bar doesn't go all - * the way to zero and don't show the mute icon. - */ - index++; - max++; - break; - } - case STREAM_REMOTE_MUSIC: { if (controller == null && sc != null) { // If we weren't passed one try using the last one set. @@ -1493,7 +1479,7 @@ public class VolumePanel extends Handler implements DemoMode { final Object tag = seekBar.getTag(); if (fromUser && tag instanceof StreamControl) { StreamControl sc = (StreamControl) tag; - setStreamVolume(sc, progress, + setStreamVolume(sc, progress + sc.minVolume, AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE); } resetTimeout(); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index bd3175fa77791..2d372d58d3511 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -249,7 +249,7 @@ public class AudioService extends IAudioService.Stub { * uses soundpool (second column) */ private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; - /** @hide Maximum volume index values for audio streams */ + /** Maximum volume index values for audio streams */ private static int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM @@ -263,6 +263,20 @@ public class AudioService extends IAudioService.Stub { 15 // STREAM_TTS }; + /** Minimum volume index values for audio streams */ + private static int[] MIN_STREAM_VOLUME = new int[] { + 1, // STREAM_VOICE_CALL + 0, // STREAM_SYSTEM + 0, // STREAM_RING + 0, // STREAM_MUSIC + 0, // STREAM_ALARM + 0, // STREAM_NOTIFICATION + 1, // STREAM_BLUETOOTH_SCO + 0, // STREAM_SYSTEM_ENFORCED + 0, // STREAM_DTMF + 0 // STREAM_TTS + }; + /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings * of another stream: This avoids multiplying the volume settings for hidden * stream types that follow other stream behavior for volume settings @@ -565,7 +579,7 @@ public class AudioService extends IAudioService.Stub { Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); - // Intialized volume + // Initialize volume int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) { @@ -586,9 +600,6 @@ public class AudioService extends IAudioService.Stub { createAudioSystemThread(); - mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), - mContext, mVolumeController, this); - AudioSystem.setErrorCallback(mAudioSystemCallback); boolean cameraSoundForced = readCameraSoundForced(); @@ -620,6 +631,9 @@ public class AudioService extends IAudioService.Stub { mSettingsObserver = new SettingsObserver(); createStreamStates(); + mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), + mContext, mVolumeController, this); + readAndSetLowRamDevice(); // Call setRingerModeInt() to apply correct mute @@ -765,6 +779,16 @@ public class AudioService extends IAudioService.Stub { mStreamStates[streamType].checkFixedVolumeDevices(); } + private void checkMuteAffectedStreams() { + // any stream with a min level > 0 is not muteable by definition + for (int i = 0; i < mStreamStates.length; i++) { + final VolumeStreamState vss = mStreamStates[i]; + if (vss.mIndexMin > 0) { + mMuteAffectedStreams &= ~(1 << vss.mStreamType); + } + } + } + private void createStreamStates() { int numStreamTypes = AudioSystem.getNumStreamTypes(); VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; @@ -775,6 +799,7 @@ public class AudioService extends IAudioService.Stub { checkAllFixedVolumeDevices(); checkAllAliasStreamVolumes(); + checkMuteAffectedStreams(); } private void dumpStreamStates(PrintWriter pw) { @@ -1617,10 +1642,6 @@ public class AudioService extends IAudioService.Stub { setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid()); } - protected static int getMaxStreamVolume(int streamType) { - return MAX_STREAM_VOLUME[streamType]; - } - /** @see AudioManager#getStreamVolume(int) */ public int getStreamVolume(int streamType) { ensureValidStreamType(streamType); @@ -1646,6 +1667,12 @@ public class AudioService extends IAudioService.Stub { return (mStreamStates[streamType].getMaxIndex() + 5) / 10; } + /** @see AudioManager#getStreamMinVolume(int) */ + public int getStreamMinVolume(int streamType) { + ensureValidStreamType(streamType); + return (mStreamStates[streamType].getMinIndex() + 5) / 10; + } + /** Get last audible volume before stream was muted. */ public int getLastAudibleStreamVolume(int streamType) { ensureValidStreamType(streamType); @@ -2279,6 +2306,7 @@ public class AudioService extends IAudioService.Stub { checkAllFixedVolumeDevices(); checkAllAliasStreamVolumes(); + checkMuteAffectedStreams(); synchronized (mSafeMediaVolumeState) { mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver, @@ -3370,10 +3398,12 @@ public class AudioService extends IAudioService.Stub { // 5 mCameraSoundForced public class VolumeStreamState { private final int mStreamType; + private final int mIndexMin; + private final int mIndexMax; private boolean mIsMuted; private String mVolumeIndexSettingName; - private int mIndexMax; + private final SparseIntArray mIndexMap = new SparseIntArray(8); private final Intent mVolumeChanged; @@ -3382,9 +3412,9 @@ public class AudioService extends IAudioService.Stub { mVolumeIndexSettingName = settingName; mStreamType = streamType; - mIndexMax = MAX_STREAM_VOLUME[streamType]; - AudioSystem.initStreamVolume(streamType, 0, mIndexMax); - mIndexMax *= 10; + mIndexMin = MIN_STREAM_VOLUME[streamType] * 10; + mIndexMax = MAX_STREAM_VOLUME[streamType] * 10; + AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10); readSettings(); mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION); @@ -3564,6 +3594,10 @@ public class AudioService extends IAudioService.Stub { return mIndexMax; } + public int getMinIndex() { + return mIndexMin; + } + public void setAllIndexes(VolumeStreamState srcStream, String caller) { synchronized (VolumeStreamState.class) { int srcStreamType = srcStream.getStreamType(); @@ -3643,8 +3677,8 @@ public class AudioService extends IAudioService.Stub { } private int getValidIndex(int index) { - if (index < 0) { - return 0; + if (index < mIndexMin) { + return mIndexMin; } else if (mUseFixedVolume || index > mIndexMax) { return mIndexMax; } @@ -3655,6 +3689,8 @@ public class AudioService extends IAudioService.Stub { private void dump(PrintWriter pw) { pw.print(" Muted: "); pw.println(mIsMuted); + pw.print(" Min: "); + pw.println((mIndexMin + 5) / 10); pw.print(" Max: "); pw.println((mIndexMax + 5) / 10); pw.print(" Current: "); diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index e945d0e7fd001..fcdd9d9ea20c5 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -102,9 +102,8 @@ public class MediaFocusControl implements OnFinished { PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent"); - mMainRemote = new RemotePlaybackState(-1, - AudioService.getMaxStreamVolume(AudioManager.STREAM_MUSIC), - AudioService.getMaxStreamVolume(AudioManager.STREAM_MUSIC)); + int maxMusicLevel = as.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + mMainRemote = new RemotePlaybackState(-1, maxMusicLevel, maxMusicLevel); // Register for phone state monitoring TelephonyManager tmgr = (TelephonyManager)