diff options
| -rw-r--r-- | media/java/android/media/AudioService.java | 89 |
1 files changed, 54 insertions, 35 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 093b1086e307..8a3fd7ab931b 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -145,7 +145,8 @@ public class AudioService extends IAudioService.Stub { private SettingsObserver mSettingsObserver; private int mMode; - private Object mSettingsLock = new Object(); + // protects mRingerMode + private final Object mSettingsLock = new Object(); private boolean mMediaServerOk; private SoundPool mSoundPool; @@ -236,6 +237,7 @@ public class AudioService extends IAudioService.Stub { * {@link AudioManager#RINGER_MODE_SILENT}, or * {@link AudioManager#RINGER_MODE_VIBRATE}. */ + // protected by mSettingsLock private int mRingerMode; /** @see System#MODE_RINGER_STREAMS_AFFECTED */ @@ -442,12 +444,15 @@ public class AudioService extends IAudioService.Stub { private void readPersistedSettings() { final ContentResolver cr = mContentResolver; - mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); + int ringerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); // sanity check in case the settings are restored from a device with incompatible // ringer modes - if (!AudioManager.isValidRingerMode(mRingerMode)) { - mRingerMode = AudioManager.RINGER_MODE_NORMAL; - System.putInt(cr, System.MODE_RINGER, mRingerMode); + if (!AudioManager.isValidRingerMode(ringerMode)) { + ringerMode = AudioManager.RINGER_MODE_NORMAL; + System.putInt(cr, System.MODE_RINGER, ringerMode); + } + synchronized(mSettingsLock) { + mRingerMode = ringerMode; } mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0); @@ -473,7 +478,7 @@ public class AudioService extends IAudioService.Stub { // Each stream will read its own persisted settings // Broadcast the sticky intent - broadcastRingerMode(); + broadcastRingerMode(ringerMode); // Broadcast vibrate settings broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); @@ -538,8 +543,9 @@ public class AudioService extends IAudioService.Stub { if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || streamTypeAlias == AudioSystem.STREAM_RING || (!mVoiceCapable && streamTypeAlias == AudioSystem.STREAM_MUSIC)) { + int ringerMode = getRingerMode(); // do not vibrate if already in vibrate mode - if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { + if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { flags &= ~AudioManager.FLAG_VIBRATE; } // Check if the ringer mode changes with this volume adjustment. If @@ -599,7 +605,7 @@ public class AudioService extends IAudioService.Stub { // setting ring or notifications volume to 0 on voice capable devices enters silent mode if (mVoiceCapable && (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || (STREAM_VOLUME_ALIAS[streamType] == AudioSystem.STREAM_RING))) { - int newRingerMode = mRingerMode; + int newRingerMode; if (index == 0) { newRingerMode = System.getInt(mContentResolver, System.VIBRATE_IN_SILENT, 1) == 1 ? AudioManager.RINGER_MODE_VIBRATE @@ -608,9 +614,7 @@ public class AudioService extends IAudioService.Stub { } else { newRingerMode = AudioManager.RINGER_MODE_NORMAL; } - if (newRingerMode != mRingerMode) { - setRingerMode(newRingerMode); - } + setRingerMode(newRingerMode); } index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]); @@ -722,22 +726,31 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#getRingerMode() */ public int getRingerMode() { - return mRingerMode; + synchronized(mSettingsLock) { + return mRingerMode; + } + } + + private void ensureValidRingerMode(int ringerMode) { + if (!AudioManager.isValidRingerMode(ringerMode)) { + throw new IllegalArgumentException("Bad ringer mode " + ringerMode); + } } /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode) { - synchronized (mSettingsLock) { - if (ringerMode != mRingerMode) { - setRingerModeInt(ringerMode, true); - // Send sticky broadcast - broadcastRingerMode(); - } + ensureValidRingerMode(ringerMode); + if (ringerMode != getRingerMode()) { + setRingerModeInt(ringerMode, true); + // Send sticky broadcast + broadcastRingerMode(ringerMode); } } private void setRingerModeInt(int ringerMode, boolean persist) { - mRingerMode = ringerMode; + synchronized(mSettingsLock) { + mRingerMode = ringerMode; + } // Mute stream if not previously muted by ringer mode and ringer mode // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. @@ -747,7 +760,7 @@ public class AudioService extends IAudioService.Stub { for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { if (isStreamMutedByRingerMode(streamType)) { if (!isStreamAffectedByRingerMode(streamType) || - mRingerMode == AudioManager.RINGER_MODE_NORMAL) { + ringerMode == AudioManager.RINGER_MODE_NORMAL) { // ring and notifications volume should never be 0 when not silenced // on voice capable devices if (mVoiceCapable && @@ -760,7 +773,7 @@ public class AudioService extends IAudioService.Stub { } } else { if (isStreamAffectedByRingerMode(streamType) && - mRingerMode != AudioManager.RINGER_MODE_NORMAL) { + ringerMode != AudioManager.RINGER_MODE_NORMAL) { mStreamStates[streamType].mute(null, true); mRingerModeMutedStreams |= (1 << streamType); } @@ -780,10 +793,10 @@ public class AudioService extends IAudioService.Stub { switch (getVibrateSetting(vibrateType)) { case AudioManager.VIBRATE_SETTING_ON: - return mRingerMode != AudioManager.RINGER_MODE_SILENT; + return getRingerMode() != AudioManager.RINGER_MODE_SILENT; case AudioManager.VIBRATE_SETTING_ONLY_SILENT: - return mRingerMode == AudioManager.RINGER_MODE_VIBRATE; + return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; case AudioManager.VIBRATE_SETTING_OFF: // return false, even for incoming calls @@ -1688,11 +1701,12 @@ public class AudioService extends IAudioService.Stub { */ private boolean checkForRingerModeChange(int oldIndex, int direction, int streamType) { boolean adjustVolumeIndex = true; - int newRingerMode = mRingerMode; + int ringerMode = getRingerMode(); + int newRingerMode = ringerMode; int uiIndex = (oldIndex + 5) / 10; boolean vibeInSilent = System.getInt(mContentResolver, System.VIBRATE_IN_SILENT, 1) == 1; - if (mRingerMode == RINGER_MODE_NORMAL) { + if (ringerMode == RINGER_MODE_NORMAL) { if ((direction == AudioManager.ADJUST_LOWER) && (uiIndex <= 1)) { // enter silent mode if current index is the last audible one and not repeating a // volume key down @@ -1707,7 +1721,7 @@ public class AudioService extends IAudioService.Stub { adjustVolumeIndex = false; } } - } else if (mRingerMode == RINGER_MODE_VIBRATE) { + } else if (ringerMode == RINGER_MODE_VIBRATE) { if ((direction == AudioManager.ADJUST_LOWER)) { // Set it to silent, if it wasn't a long-press if (mPrevVolDirection != AudioManager.ADJUST_LOWER) { @@ -1726,9 +1740,7 @@ public class AudioService extends IAudioService.Stub { adjustVolumeIndex = false; } - if (newRingerMode != mRingerMode) { - setRingerMode(newRingerMode); - } + setRingerMode(newRingerMode); mPrevVolDirection = direction; @@ -1818,10 +1830,10 @@ public class AudioService extends IAudioService.Stub { } } - private void broadcastRingerMode() { + private void broadcastRingerMode(int ringerMode) { // Send sticky broadcast Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION); - broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, mRingerMode); + broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_REPLACE_PENDING); long origCallerIdentityToken = Binder.clearCallingIdentity(); @@ -2013,7 +2025,8 @@ public class AudioService extends IAudioService.Stub { if (muteCount() == 0) { // If the stream is not muted any more, restore it's volume if // ringer mode allows it - if (!isStreamAffectedByRingerMode(mStreamType) || mRingerMode == AudioManager.RINGER_MODE_NORMAL) { + if (!isStreamAffectedByRingerMode(mStreamType) || + getRingerMode() == AudioManager.RINGER_MODE_NORMAL) { setIndex(mLastAudibleIndex, false); sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, SENDMSG_NOOP, 0, 0, VolumeStreamState.this, 0); @@ -2131,8 +2144,8 @@ public class AudioService extends IAudioService.Stub { } } - private void persistRingerMode() { - System.putInt(mContentResolver, System.MODE_RINGER, mRingerMode); + private void persistRingerMode(int ringerMode) { + System.putInt(mContentResolver, System.MODE_RINGER, ringerMode); } private void persistVibrateSetting() { @@ -2219,7 +2232,9 @@ public class AudioService extends IAudioService.Stub { break; case MSG_PERSIST_RINGER_MODE: - persistRingerMode(); + // note that the value persisted is the current ringer mode, not the + // value of ringer mode as of the time the request was made to persist + persistRingerMode(getRingerMode()); break; case MSG_PERSIST_VIBRATE_SETTING: @@ -2335,6 +2350,10 @@ public class AudioService extends IAudioService.Stub { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); + // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. + // However there appear to be some missing locks around mRingerModeMutedStreams + // and mRingerModeAffectedStreams, so will leave this synchronized for now. + // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). synchronized (mSettingsLock) { int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, Settings.System.MODE_RINGER_STREAMS_AFFECTED, |