diff options
-rw-r--r-- | core/jni/android_media_AudioSystem.cpp | 6 | ||||
-rw-r--r-- | include/media/AudioSystem.h | 5 | ||||
-rw-r--r-- | include/media/IAudioFlinger.h | 3 | ||||
-rw-r--r-- | include/media/IAudioPolicyService.h | 1 | ||||
-rw-r--r-- | media/java/android/media/AudioManager.java | 44 | ||||
-rw-r--r-- | media/java/android/media/AudioService.java | 182 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 2 | ||||
-rw-r--r-- | media/java/android/media/IAudioService.aidl | 6 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 17 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 16 | ||||
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 20 | ||||
-rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java | 29 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 25 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 4 | ||||
-rw-r--r-- | services/audioflinger/AudioPolicyManagerBase.cpp | 27 | ||||
-rw-r--r-- | services/audioflinger/AudioPolicyService.cpp | 9 | ||||
-rw-r--r-- | services/audioflinger/AudioPolicyService.h | 5 |
17 files changed, 256 insertions, 145 deletions
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 40b9334..5147cfa 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -64,10 +64,10 @@ android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz) } static jboolean -android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream) +android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs) { bool state = false; - AudioSystem::isStreamActive(stream, &state); + AudioSystem::isStreamActive(stream, &state, inPastMs); return state; } @@ -199,7 +199,7 @@ static JNINativeMethod gMethods[] = { {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters}, {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone}, {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted}, - {"isStreamActive", "(I)Z", (void *)android_media_AudioSystem_isStreamActive}, + {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive}, {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 1e29d82..03f8944 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -204,8 +204,9 @@ public: // set audio mode in audio hardware (see AudioSystem::audio_mode) static status_t setMode(int mode); - // returns true in *state if tracks are active on the specified stream - static status_t isStreamActive(int stream, bool *state); + // returns true in *state if tracks are active on the specified stream or has been active + // in the past inPastMs milliseconds + static status_t isStreamActive(int stream, bool *state, uint32_t inPastMs = 0); // set/get audio hardware parameters. The function accepts a list of parameters // key value pairs in the form: key1=value1;key2=value2;... diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 70e505e..589f7cd 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -102,9 +102,6 @@ public: virtual status_t setMicMute(bool state) = 0; virtual bool getMicMute() const = 0; - // is any track active on this stream? - virtual bool isStreamActive(int stream) const = 0; - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) = 0; virtual String8 getParameters(int ioHandle, const String8& keys) = 0; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 49eee59..5afceaa 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -81,6 +81,7 @@ public: int session, int id) = 0; virtual status_t unregisterEffect(int id) = 0; + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0; }; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 9058a7b..051a0fc 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -394,10 +394,10 @@ public class AudioManager { */ adjustSuggestedStreamVolume( keyCode == KeyEvent.KEYCODE_VOLUME_UP - ? AudioManager.ADJUST_RAISE - : AudioManager.ADJUST_LOWER, + ? ADJUST_RAISE + : ADJUST_LOWER, stream, - AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE); + FLAG_SHOW_UI | FLAG_VIBRATE); break; case KeyEvent.KEYCODE_VOLUME_MUTE: // TODO: Actually handle MUTE. @@ -416,7 +416,11 @@ public class AudioManager { * 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. */ - adjustSuggestedStreamVolume(ADJUST_SAME, stream, FLAG_PLAY_SOUND); + adjustSuggestedStreamVolume( + ADJUST_SAME, + stream, + FLAG_PLAY_SOUND); + mVolumeKeyUpTime = SystemClock.uptimeMillis(); break; case KeyEvent.KEYCODE_VOLUME_MUTE: @@ -555,6 +559,21 @@ public class AudioManager { } /** + * Get last audible volume before stream was muted. + * + * @hide + */ + public int getLastAudibleStreamVolume(int streamType) { + IAudioService service = getService(); + try { + return service.getLastAudibleStreamVolume(streamType); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e); + return 0; + } + } + + /** * Sets the ringer mode. * <p> * Silent mode will mute the volume and will not vibrate. Vibrate mode will @@ -649,6 +668,21 @@ public class AudioManager { } /** + * get stream mute state. + * + * @hide + */ + public boolean isStreamMute(int streamType) { + IAudioService service = getService(); + try { + return service.isStreamMute(streamType); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in isStreamMute", e); + return false; + } + } + + /** * Returns whether a particular type should vibrate according to user * settings and the current ringer mode. * <p> @@ -1124,7 +1158,7 @@ public class AudioManager { * @return true if any music tracks are active. */ public boolean isMusicActive() { - return AudioSystem.isStreamActive(STREAM_MUSIC); + return AudioSystem.isStreamActive(STREAM_MUSIC, 0); } /* diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index cbc7529..e18220a 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -284,6 +284,15 @@ public class AudioService extends IAudioService.Stub { private SoundPoolListenerThread mSoundPoolListenerThread; // message looper for SoundPool listener private Looper mSoundPoolLooper = null; + // default volume applied to sound played with playSoundEffect() + private static final int SOUND_EFFECT_DEFAULT_VOLUME_DB = -20; + // volume applied to sound played with playSoundEffect() read from ro.config.sound_fx_volume + private int SOUND_EFFECT_VOLUME_DB; + // getActiveStreamType() will return STREAM_NOTIFICATION during this period after a notification + // stopped + private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000; + // previous volume adjustment direction received by checkForRingerModeChange() + private int mPrevVolDirection = AudioManager.ADJUST_SAME; /////////////////////////////////////////////////////////////////////////// // Construction @@ -301,6 +310,10 @@ public class AudioService extends IAudioService.Stub { "ro.config.vc_call_vol_steps", MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); + SOUND_EFFECT_VOLUME_DB = SystemProperties.getInt( + "ro.config.sound_fx_volume", + SOUND_EFFECT_DEFAULT_VOLUME_DB); + mVolumePanel = new VolumePanel(context, this); mSettingsObserver = new SettingsObserver(); mForcedUseForComm = AudioSystem.FORCE_NONE; @@ -401,14 +414,19 @@ public class AudioService extends IAudioService.Stub { mRingerModeAffectedStreams = Settings.System.getInt(cr, Settings.System.MODE_RINGER_STREAMS_AFFECTED, ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| - (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED))); + (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)| + (1 << AudioSystem.STREAM_MUSIC))); mMuteAffectedStreams = System.getInt(cr, System.MUTE_STREAMS_AFFECTED, ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM))); - mNotificationsUseRingVolume = System.getInt(cr, - Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1); + if (mVoiceCapable) { + mNotificationsUseRingVolume = System.getInt(cr, + Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1); + } else { + mNotificationsUseRingVolume = 1; + } if (mNotificationsUseRingVolume == 1) { STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; @@ -465,8 +483,10 @@ public class AudioService extends IAudioService.Stub { // If either the client forces allowing ringer modes for this adjustment, // or the stream type is one that is affected by ringer modes - if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0 - || streamType == AudioSystem.STREAM_RING) { + if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || + (!mVoiceCapable && streamType != AudioSystem.STREAM_VOICE_CALL && + streamType != AudioSystem.STREAM_BLUETOOTH_SCO) || + (mVoiceCapable && streamType == AudioSystem.STREAM_RING)) { // Check if the ringer mode changes with this volume adjustment. If // it does, it will handle adjusting the volume, so we won't below adjustVolume = checkForRingerModeChange(oldIndex, direction); @@ -491,10 +511,8 @@ public class AudioService extends IAudioService.Stub { } index = streamState.mIndex; } - // UI - mVolumePanel.postVolumeChanged(streamType, flags); - // Broadcast Intent - sendVolumeUpdate(streamType, oldIndex, index); + + sendVolumeUpdate(streamType, oldIndex, index, flags); } /** @see AudioManager#setStreamVolume(int, int, int) */ @@ -509,21 +527,23 @@ public class AudioService extends IAudioService.Stub { index = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex; - // UI, etc. - mVolumePanel.postVolumeChanged(streamType, flags); - // Broadcast Intent - sendVolumeUpdate(streamType, oldIndex, index); + sendVolumeUpdate(streamType, oldIndex, index, flags); } - private void sendVolumeUpdate(int streamType, int oldIndex, int index) { + // UI update and Broadcast Intent + private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { + if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { + streamType = AudioSystem.STREAM_NOTIFICATION; + } + + mVolumePanel.postVolumeChanged(streamType, flags); + oldIndex = (oldIndex + 5) / 10; index = (index + 5) / 10; - Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); - mContext.sendBroadcast(intent); } @@ -575,6 +595,11 @@ public class AudioService extends IAudioService.Stub { } } + /** get stream mute state. */ + public boolean isStreamMute(int streamType) { + return (mStreamStates[streamType].muteCount() != 0); + } + /** @see AudioManager#getStreamVolume(int) */ public int getStreamVolume(int streamType) { ensureValidStreamType(streamType); @@ -587,6 +612,13 @@ public class AudioService extends IAudioService.Stub { return (mStreamStates[streamType].getMaxIndex() + 5) / 10; } + + /** Get last audible volume before stream was muted. */ + public int getLastAudibleStreamVolume(int streamType) { + ensureValidStreamType(streamType); + return (mStreamStates[streamType].mLastAudibleIndex + 5) / 10; + } + /** @see AudioManager#getRingerMode() */ public int getRingerMode() { return mRingerMode; @@ -1383,8 +1415,9 @@ public class AudioService extends IAudioService.Stub { if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { // audible mode, at the bottom of the scale - if (direction == AudioManager.ADJUST_LOWER - && (oldIndex + 5) / 10 == 1) { + if ((direction == AudioManager.ADJUST_LOWER && + mPrevVolDirection != AudioManager.ADJUST_LOWER) && + ((oldIndex + 5) / 10 == 0)) { // "silent mode", but which one? newRingerMode = System.getInt(mContentResolver, System.VIBRATE_IN_SILENT, 1) == 1 ? AudioManager.RINGER_MODE_VIBRATE @@ -1411,6 +1444,8 @@ public class AudioService extends IAudioService.Stub { adjustVolumeIndex = false; } + mPrevVolDirection = direction; + return adjustVolumeIndex; } @@ -1439,36 +1474,61 @@ public class AudioService extends IAudioService.Stub { } private int getActiveStreamType(int suggestedStreamType) { - boolean isOffhook = false; - try { - ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); - if (phone != null) isOffhook = phone.isOffhook(); - } catch (RemoteException e) { - Log.w(TAG, "Couldn't connect to phone service", e); - } - - if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) { - // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); - return AudioSystem.STREAM_BLUETOOTH_SCO; - } else if (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION) { - // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); - return AudioSystem.STREAM_VOICE_CALL; - } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC)) { - // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC..."); - return AudioSystem.STREAM_MUSIC; - } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { - if (mVoiceCapable) { + + if (mVoiceCapable) { + boolean isOffhook = false; + try { + ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); + if (phone != null) isOffhook = phone.isOffhook(); + } catch (RemoteException e) { + Log.w(TAG, "Couldn't connect to phone service", e); + } + + if (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION) { + if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) + == AudioSystem.FORCE_BT_SCO) { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); + return AudioSystem.STREAM_BLUETOOTH_SCO; + } else { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); + return AudioSystem.STREAM_VOICE_CALL; + } + } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC..."); + return AudioSystem.STREAM_MUSIC; + } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { // Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING..." // + " b/c USE_DEFAULT_STREAM_TYPE..."); return AudioSystem.STREAM_RING; } else { + // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType); + return suggestedStreamType; + } + } else { + if (getMode() == AudioManager.MODE_IN_COMMUNICATION) { + if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) + == AudioSystem.FORCE_BT_SCO) { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); + return AudioSystem.STREAM_BLUETOOTH_SCO; + } else { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); + return AudioSystem.STREAM_VOICE_CALL; + } + } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, + NOTIFICATION_VOLUME_DELAY_MS) || + AudioSystem.isStreamActive(AudioSystem.STREAM_RING, + NOTIFICATION_VOLUME_DELAY_MS)) { + // Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION..."); + return AudioSystem.STREAM_NOTIFICATION; + } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) || + (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE)) { // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC " // + " b/c USE_DEFAULT_STREAM_TYPE..."); return AudioSystem.STREAM_MUSIC; + } else { + // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType); + return suggestedStreamType; } - } else { - // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType); - return suggestedStreamType; } } @@ -1801,13 +1861,9 @@ public class AudioService extends IAudioService.Stub { return; } float volFloat; - // use STREAM_MUSIC volume attenuated by 3 dB if volume is not specified by caller + // use default if volume is not specified by caller if (volume < 0) { - // Same linear to log conversion as in native AudioSystem::linearToLog() (AudioSystem.cpp) - float dBPerStep = (float)((0.5 * 100) / MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); - int musicVolIndex = (mStreamStates[AudioSystem.STREAM_MUSIC].mIndex + 5) / 10; - float musicVoldB = dBPerStep * (musicVolIndex - MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); - volFloat = (float)Math.pow(10, (musicVoldB - 3)/20); + volFloat = (float)Math.pow(10, SOUND_EFFECT_VOLUME_DB/20); } else { volFloat = (float) volume / 1000.0f; } @@ -1884,7 +1940,7 @@ public class AudioService extends IAudioService.Stub { // Force creation of new IAudioflinger interface if (!mMediaServerOk) { Log.e(TAG, "Media server died."); - AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC); + AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0); sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SHARED_MSG, SENDMSG_NOOP, 0, 0, null, 500); } @@ -1981,21 +2037,23 @@ public class AudioService extends IAudioService.Stub { int notificationsUseRingVolume = Settings.System.getInt(mContentResolver, Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1); - if (notificationsUseRingVolume != mNotificationsUseRingVolume) { - mNotificationsUseRingVolume = notificationsUseRingVolume; - if (mNotificationsUseRingVolume == 1) { - STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; - mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName( - System.VOLUME_SETTINGS[AudioSystem.STREAM_RING]); - } else { - STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION; - mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName( - System.VOLUME_SETTINGS[AudioSystem.STREAM_NOTIFICATION]); - // Persist notification volume volume as it was not persisted while aliased to ring volume - // and persist with no delay as there might be registered observers of the persisted - // notification volume. - sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, AudioSystem.STREAM_NOTIFICATION, - SENDMSG_REPLACE, 1, 1, mStreamStates[AudioSystem.STREAM_NOTIFICATION], 0); + if (mVoiceCapable) { + if (notificationsUseRingVolume != mNotificationsUseRingVolume) { + mNotificationsUseRingVolume = notificationsUseRingVolume; + if (mNotificationsUseRingVolume == 1) { + STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; + mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName( + System.VOLUME_SETTINGS[AudioSystem.STREAM_RING]); + } else { + STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION; + mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName( + System.VOLUME_SETTINGS[AudioSystem.STREAM_NOTIFICATION]); + // Persist notification volume volume as it was not persisted while aliased to ring volume + // and persist with no delay as there might be registered observers of the persisted + // notification volume. + sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, AudioSystem.STREAM_NOTIFICATION, + SENDMSG_REPLACE, 1, 1, mStreamStates[AudioSystem.STREAM_NOTIFICATION], 0); + } } } } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 1fd03dc..e20bb25 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -158,7 +158,7 @@ public class AudioSystem * * return true if any track playing on this stream is active. */ - public static native boolean isStreamActive(int stream); + public static native boolean isStreamActive(int stream, int inPastMs); /* * Sets a group generic audio configuration parameters. The use of these parameters diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 384b8da..e3bd7b4 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -35,11 +35,15 @@ interface IAudioService { void setStreamSolo(int streamType, boolean state, IBinder cb); void setStreamMute(int streamType, boolean state, IBinder cb); - + + boolean isStreamMute(int streamType); + int getStreamVolume(int streamType); int getStreamMaxVolume(int streamType); + int getLastAudibleStreamVolume(int streamType); + void setRingerMode(int ringerMode); int getRingerMode(); diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1a3fcd6..9d9b3c0 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -169,15 +169,6 @@ status_t AudioSystem::setMode(int mode) return af->setMode(mode); } - -status_t AudioSystem::isStreamActive(int stream, bool* state) { - const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *state = af->isStreamActive(stream); - return NO_ERROR; -} - - status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; @@ -702,6 +693,14 @@ status_t AudioSystem::unregisterEffect(int id) return aps->unregisterEffect(id); } +status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) { + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + *state = aps->isStreamActive(stream, inPastMs); + return NO_ERROR; +} + + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 3a89e25..eec47c0 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -47,7 +47,6 @@ enum { SET_MODE, SET_MIC_MUTE, GET_MIC_MUTE, - IS_STREAM_ACTIVE, SET_PARAMETERS, GET_PARAMETERS, REGISTER_CLIENT, @@ -316,15 +315,6 @@ public: return reply.readInt32(); } - virtual bool isStreamActive(int stream) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - remote()->transact(IS_STREAM_ACTIVE, data, &reply); - return reply.readInt32(); - } - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) { Parcel data, reply; @@ -826,12 +816,6 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( getMicMute() ); return NO_ERROR; } break; - case IS_STREAM_ACTIVE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeInt32( isStreamActive(stream) ); - return NO_ERROR; - } break; case SET_PARAMETERS: { CHECK_INTERFACE(IAudioFlinger, data, reply); int ioHandle = data.readInt32(); diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 950c213..457f7ed 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -48,7 +48,8 @@ enum { GET_STRATEGY_FOR_STREAM, GET_OUTPUT_FOR_EFFECT, REGISTER_EFFECT, - UNREGISTER_EFFECT + UNREGISTER_EFFECT, + IS_STREAM_ACTIVE }; class BpAudioPolicyService : public BpInterface<IAudioPolicyService> @@ -297,6 +298,15 @@ public: return static_cast <status_t> (reply.readInt32()); } + virtual bool isStreamActive(int stream, uint32_t inPastMs) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeInt32(inPastMs); + remote()->transact(IS_STREAM_ACTIVE, data, &reply); + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -517,6 +527,14 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case IS_STREAM_ACTIVE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + int stream = data.readInt32(); + uint32_t inPastMs = (uint32_t)data.readInt32(); + reply->writeInt32( isStreamActive(stream, inPastMs) ); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 49b71e2..f336f06 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -61,7 +61,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 63; + private static final int DATABASE_VERSION = 64; private Context mContext; @@ -797,6 +797,28 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 63; } + if (upgradeVersion == 63) { + // This upgrade adds the STREAM_MUSIC type to the list of + // types affected by ringer modes (silent, vibrate, etc.) + db.beginTransaction(); + try { + db.execSQL("DELETE FROM system WHERE name='" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'"); + int newValue = (1 << AudioManager.STREAM_RING) + | (1 << AudioManager.STREAM_NOTIFICATION) + | (1 << AudioManager.STREAM_SYSTEM) + | (1 << AudioManager.STREAM_SYSTEM_ENFORCED) + | (1 << AudioManager.STREAM_MUSIC); + db.execSQL("INSERT INTO system ('name', 'value') values ('" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '" + + String.valueOf(newValue) + "')"); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + upgradeVersion = 64; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { @@ -1057,10 +1079,11 @@ public class DatabaseHelper extends SQLiteOpenHelper { loadVibrateSetting(db, false); - // By default, only the ring/notification and system streams are affected + // By default, only the ring/notification, system and music streams are affected loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED, (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) | - (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED)); + (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED) | + (1 << AudioManager.STREAM_MUSIC)); loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED, ((1 << AudioManager.STREAM_MUSIC) | diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 11ad4e4..4ec16c1 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -624,17 +624,6 @@ bool AudioFlinger::streamMute(int stream) const return mStreamTypes[stream].mute; } -bool AudioFlinger::isStreamActive(int stream) const -{ - Mutex::Autolock _l(mLock); - for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) { - if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) { - return true; - } - } - return false; -} - status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) { status_t result; @@ -1291,20 +1280,6 @@ bool AudioFlinger::PlaybackThread::streamMute(int stream) const return mStreamTypes[stream].mute; } -bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const -{ - Mutex::Autolock _l(mLock); - size_t count = mActiveTracks.size(); - for (size_t i = 0 ; i < count ; ++i) { - sp<Track> t = mActiveTracks[i].promote(); - if (t == 0) continue; - Track* const track = t.get(); - if (t->type() == stream) - return true; - } - return false; -} - // addTrack_l() must be called with ThreadBase::mLock held status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index f0ef867..81f2eb4 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -107,8 +107,6 @@ public: virtual status_t setMicMute(bool state); virtual bool getMicMute() const; - virtual bool isStreamActive(int stream) const; - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs); virtual String8 getParameters(int ioHandle, const String8& keys); @@ -579,8 +577,6 @@ private: virtual float streamVolume(int stream) const; virtual bool streamMute(int stream) const; - bool isStreamActive(int stream) const; - sp<Track> createTrack_l( const sp<AudioFlinger::Client>& client, int streamType, diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp index e84d136..04d63e6 100644 --- a/services/audioflinger/AudioPolicyManagerBase.cpp +++ b/services/audioflinger/AudioPolicyManagerBase.cpp @@ -313,8 +313,7 @@ void AudioPolicyManagerBase::setPhoneState(int state) // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && - (hwOutputDesc->mRefCount[AudioSystem::MUSIC] || - (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { + isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; @@ -479,6 +478,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str outputDesc->mLatency = 0; outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT); outputDesc->mRefCount[stream] = 0; + outputDesc->mStopTime[stream] = 0; output = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, @@ -607,10 +607,8 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, if (outputDesc->mRefCount[stream] > 0) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); - // store time at which the last music track was stopped - see computeVolume() - if (stream == AudioSystem::MUSIC) { - mMusicStopTime = systemTime(); - } + // store time at which the stream was stopped - see isStreamActive() + outputDesc->mStopTime[stream] = systemTime(); setOutputDevice(output, getNewDevice(output)); @@ -920,6 +918,19 @@ status_t AudioPolicyManagerBase::unregisterEffect(int id) return NO_ERROR; } +bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const +{ + nsecs_t sysTime = systemTime(); + for (size_t i = 0; i < mOutputs.size(); i++) { + if (mOutputs.valueAt(i)->mRefCount[stream] != 0 || + ns2ms(sysTime - mOutputs.valueAt(i)->mStopTime[stream]) < inPastMs) { + return true; + } + } + return false; +} + + status_t AudioPolicyManagerBase::dump(int fd) { const size_t SIZE = 256; @@ -1010,7 +1021,7 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien Thread(false), #endif //AUDIO_POLICY_TEST mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), - mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), + mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), mA2dpSuspended(false) { @@ -2094,6 +2105,7 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor() mRefCount[i] = 0; mCurVolume[i] = -1.0; mMuteCount[i] = 0; + mStopTime[i] = 0; } } @@ -2144,7 +2156,6 @@ uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing return refCount; } - status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd) { const size_t SIZE = 256; diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 46a01ad..b04672d 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -394,6 +394,15 @@ status_t AudioPolicyService::unregisterEffect(int id) return mpPolicyManager->unregisterEffect(id); } +bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const +{ + if (mpPolicyManager == NULL) { + return 0; + } + Mutex::Autolock _l(mLock); + return mpPolicyManager->isStreamActive(stream, inPastMs); +} + void AudioPolicyService::binderDied(const wp<IBinder>& who) { LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index 558f455..54af1f1 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -88,6 +88,7 @@ public: int session, int id); virtual status_t unregisterEffect(int id); + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const; virtual status_t onTransact( uint32_t code, @@ -230,8 +231,8 @@ private: status_t dumpPermissionDenial(int fd); - Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device - // connection stated our routing + mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing + // device connection state or routing AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager sp <AudioCommandThread> mAudioCommandThread; // audio commands thread sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread |