summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_media_AudioSystem.cpp6
-rw-r--r--include/media/AudioSystem.h5
-rw-r--r--include/media/IAudioFlinger.h3
-rw-r--r--include/media/IAudioPolicyService.h1
-rw-r--r--media/java/android/media/AudioManager.java44
-rw-r--r--media/java/android/media/AudioService.java182
-rw-r--r--media/java/android/media/AudioSystem.java2
-rw-r--r--media/java/android/media/IAudioService.aidl6
-rw-r--r--media/libmedia/AudioSystem.cpp17
-rw-r--r--media/libmedia/IAudioFlinger.cpp16
-rw-r--r--media/libmedia/IAudioPolicyService.cpp20
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java29
-rw-r--r--services/audioflinger/AudioFlinger.cpp25
-rw-r--r--services/audioflinger/AudioFlinger.h4
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp27
-rw-r--r--services/audioflinger/AudioPolicyService.cpp9
-rw-r--r--services/audioflinger/AudioPolicyService.h5
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 2c81c34..afa9acc 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -312,8 +312,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;
@@ -478,6 +477,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,
@@ -606,10 +606,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));
@@ -919,6 +917,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;
@@ -1009,7 +1020,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)
{
@@ -2036,6 +2047,7 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
mRefCount[i] = 0;
mCurVolume[i] = -1.0;
mMuteCount[i] = 0;
+ mStopTime[i] = 0;
}
}
@@ -2086,7 +2098,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