Merge "AudioService: Observe changes to output devices per-stream."
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 28941b9..cb70e8b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -134,6 +134,22 @@
public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
/**
+ * @hide Broadcast intent when the devices for a particular stream type changes.
+ * Includes the stream, the new devices and previous devices.
+ * Notes:
+ * - for internal platform use only, do not make public,
+ * - never used for "remote" volume changes
+ *
+ * @see #EXTRA_VOLUME_STREAM_TYPE
+ * @see #EXTRA_VOLUME_STREAM_DEVICES
+ * @see #EXTRA_PREV_VOLUME_STREAM_DEVICES
+ * @see #getDevicesForStream
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String STREAM_DEVICES_CHANGED_ACTION =
+ "android.media.STREAM_DEVICES_CHANGED_ACTION";
+
+ /**
* @hide Broadcast intent when a stream mute state changes.
* Includes the stream that changed and the new mute state
*
@@ -196,6 +212,18 @@
"android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
/**
+ * @hide The devices associated with the stream for the stream devices changed intent.
+ */
+ public static final String EXTRA_VOLUME_STREAM_DEVICES =
+ "android.media.EXTRA_VOLUME_STREAM_DEVICES";
+
+ /**
+ * @hide The previous devices associated with the stream for the stream devices changed intent.
+ */
+ public static final String EXTRA_PREV_VOLUME_STREAM_DEVICES =
+ "android.media.EXTRA_PREV_VOLUME_STREAM_DEVICES";
+
+ /**
* @hide The new master volume mute state for the master mute changed intent.
* Value is boolean
*/
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 983d83a..694e851 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -221,3 +221,4 @@
# AudioService.java
# ---------------------------
40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
+40001 stream_devices_changed (stream|1), (prev_devices|1), (devices|1)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9d311f9..1eddc8e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3299,7 +3299,7 @@
}
private int getDeviceForStream(int stream) {
- int device = AudioSystem.getDevicesForStream(stream);
+ int device = getDevicesForStream(stream);
if ((device & (device - 1)) != 0) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
@@ -3322,6 +3322,27 @@
return device;
}
+ private int getDevicesForStream(int stream) {
+ return getDevicesForStream(stream, true /*checkOthers*/);
+ }
+
+ private int getDevicesForStream(int stream, boolean checkOthers) {
+ ensureValidStreamType(stream);
+ synchronized (VolumeStreamState.class) {
+ return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
+ }
+ }
+
+ private void observeDevicesForStreams(int skipStream) {
+ synchronized (VolumeStreamState.class) {
+ for (int stream = 0; stream < mStreamStates.length; stream++) {
+ if (stream != skipStream) {
+ mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
+ }
+ }
+ }
+ }
+
/*
* A class just for packaging up a set of connection parameters.
*/
@@ -3400,9 +3421,11 @@
private boolean mIsMuted;
private String mVolumeIndexSettingName;
+ private int mObservedDevices;
private final SparseIntArray mIndexMap = new SparseIntArray(8);
private final Intent mVolumeChanged;
+ private final Intent mStreamDevicesChanged;
private VolumeStreamState(String settingName, int streamType) {
@@ -3416,6 +3439,29 @@
readSettings();
mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+ mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ }
+
+ public int observeDevicesForStream_syncVSS(boolean checkOthers) {
+ final int devices = AudioSystem.getDevicesForStream(mStreamType);
+ if (devices == mObservedDevices) {
+ return devices;
+ }
+ final int prevDevices = mObservedDevices;
+ mObservedDevices = devices;
+ if (checkOthers) {
+ // one stream's devices have changed, check the others
+ observeDevicesForStreams(mStreamType);
+ }
+ // log base stream changes to the event log
+ if (mStreamVolumeAlias[mStreamType] == mStreamType) {
+ EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
+ }
+ sendBroadcastToAll(mStreamDevicesChanged
+ .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
+ .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
+ return devices;
}
public String getSettingNameForDevice(int device) {
@@ -3710,7 +3756,7 @@
}
pw.println();
pw.print(" Devices: ");
- final int devices = AudioSystem.getDevicesForStream(mStreamType);
+ final int devices = getDevicesForStream(mStreamType);
int device, i = 0, n = 0;
// iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
// (the default device is not returned by getDevicesForStream)
@@ -4244,6 +4290,7 @@
}
}
mRoutesObservers.finishBroadcast();
+ observeDevicesForStreams(-1);
break;
}
@@ -5342,7 +5389,7 @@
on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
AudioSystem.FORCE_NONE);
}
- device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
}
}
}