Loading services/core/java/com/android/server/audio/AudioService.java +116 −34 Original line number Diff line number Diff line Loading @@ -285,6 +285,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_PLAYBACK_CONFIG_CHANGE = 29; private static final int MSG_BROADCAST_MICROPHONE_MUTE = 30; private static final int MSG_CHECK_MODE_FOR_UID = 31; private static final int MSG_STREAM_DEVICES_CHANGED = 32; private static final int MSG_UPDATE_VOLUME_STATES_FOR_DEVICE = 33; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) Loading Loading @@ -1283,7 +1285,6 @@ public class AudioService extends IAudioService.Stub } if (isPlatformTelevision()) { checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller); synchronized (mHdmiClientLock) { if (mHdmiManager != null && mHdmiPlaybackClient != null) { updateHdmiCecSinkLocked(mHdmiCecSink | false); Loading @@ -1303,9 +1304,50 @@ public class AudioService extends IAudioService.Stub } } private void checkAddAllFixedVolumeDevices(int device, String caller) { /** * Asynchronously update volume states for the given device. * * @param device a single audio device, ensure that this is not a devices bitmask * @param caller caller of this method */ private void postUpdateVolumeStatesForAudioDevice(int device, String caller) { sendMsg(mAudioHandler, MSG_UPDATE_VOLUME_STATES_FOR_DEVICE, SENDMSG_QUEUE, device /*arg1*/, 0 /*arg2*/, caller /*obj*/, 0 /*delay*/); } /** * Update volume states for the given device. * * This will initialize the volume index if no volume index is available. * If the device is the currently routed device, fixed/full volume policies will be applied. * * @param device a single audio device, ensure that this is not a devices bitmask * @param caller caller of this method */ private void onUpdateVolumeStatesForAudioDevice(int device, String caller) { final int numStreamTypes = AudioSystem.getNumStreamTypes(); synchronized (mSettingsLock) { synchronized (VolumeStreamState.class) { for (int streamType = 0; streamType < numStreamTypes; streamType++) { updateVolumeStates(device, streamType, caller); } } } } /** * Update volume states for the given device and given stream. * * This will initialize the volume index if no volume index is available. * If the device is the currently routed device, fixed/full volume policies will be applied. * * @param device a single audio device, ensure that this is not a devices bitmask * @param streamType streamType to be updated * @param caller caller of this method */ private void updateVolumeStates(int device, int streamType, String caller) { if (!mStreamStates[streamType].hasIndexForDevice(device)) { // set the default value, if device is affected by a full/fix/abs volume rule, it // will taken into account in checkFixedVolumeDevices() Loading @@ -1314,14 +1356,22 @@ public class AudioService extends IAudioService.Stub .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), device, caller, true /*hasModifyAudioSettings*/); } // Check if device to be updated is routed for the given audio stream List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt( new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build()); for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) { if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType( device)) { mStreamStates[streamType].checkFixedVolumeDevices(); // Unmute streams if device is full volume if (mFullVolumeDevices.contains(device)) { // Unmute streams if required and device is full volume if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) { mStreamStates[streamType].mute(false); } } } } private void checkAllFixedVolumeDevices() { Loading Loading @@ -1868,8 +1918,13 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */ public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); enforceModifyAudioRoutingPermission(); return getDevicesForAttributesInt(attributes); } protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); return AudioSystem.getDevicesForAttributes(attributes); } Loading Loading @@ -4912,11 +4967,21 @@ public class AudioService extends IAudioService.Stub } } private void observeDevicesForStreams(int skipStream) { private void onObserveDevicesForAllStreams(int skipStream) { synchronized (mSettingsLock) { synchronized (VolumeStreamState.class) { for (int stream = 0; stream < mStreamStates.length; stream++) { if (stream != skipStream) { mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/); int devices = mStreamStates[stream].observeDevicesForStream_syncVSS( false /*checkOthers*/); Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices); for (Integer device : devicesSet) { // Update volume states for devices routed for the stream updateVolumeStates(device, stream, "AudioService#onObserveDevicesForAllStreams"); } } } } } Loading @@ -4925,16 +4990,18 @@ public class AudioService extends IAudioService.Stub /** only public for mocking/spying, do not call outside of AudioService */ @VisibleForTesting public void postObserveDevicesForAllStreams() { postObserveDevicesForAllStreams(-1); } /** only public for mocking/spying, do not call outside of AudioService */ @VisibleForTesting public void postObserveDevicesForAllStreams(int skipStream) { sendMsg(mAudioHandler, MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS, SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/, SENDMSG_QUEUE, skipStream /*arg1*/, 0 /*arg2*/, null /*obj*/, 0 /*delay*/); } private void onObserveDevicesForAllStreams() { observeDevicesForStreams(-1); } /** * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int) * @param device the audio device to be affected Loading Loading @@ -4985,7 +5052,8 @@ public class AudioService extends IAudioService.Stub + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); postUpdateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); } /** Loading Loading @@ -5616,6 +5684,7 @@ public class AudioService extends IAudioService.Stub } } @GuardedBy("VolumeStreamState.class") public int observeDevicesForStream_syncVSS(boolean checkOthers) { if (!mSystemServer.isPrivileged()) { return AudioSystem.DEVICE_NONE; Loading @@ -5628,15 +5697,19 @@ public class AudioService extends IAudioService.Stub mObservedDevices = devices; if (checkOthers) { // one stream's devices have changed, check the others observeDevicesForStreams(mStreamType); postObserveDevicesForAllStreams(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)); // send STREAM_DEVICES_CHANGED_ACTION on the message handler so it is scheduled after // the postObserveDevicesForStreams is handled sendMsg(mAudioHandler, MSG_STREAM_DEVICES_CHANGED, SENDMSG_QUEUE, prevDevices /*arg1*/, devices /*arg2*/, // ok to send reference to this object, it is final mStreamDevicesChanged /*obj*/, 0 /*delay*/); return devices; } Loading Loading @@ -6408,7 +6481,7 @@ public class AudioService extends IAudioService.Stub break; case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS: onObserveDevicesForAllStreams(); onObserveDevicesForAllStreams(/*skipStream*/ msg.arg1); break; case MSG_HDMI_VOLUME_CHECK: Loading Loading @@ -6451,6 +6524,16 @@ public class AudioService extends IAudioService.Stub mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid())); } break; case MSG_STREAM_DEVICES_CHANGED: sendBroadcastToAll(((Intent) msg.obj) .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, msg.arg1) .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, msg.arg2)); break; case MSG_UPDATE_VOLUME_STATES_FOR_DEVICE: onUpdateVolumeStatesForAudioDevice(msg.arg1, (String) msg.obj); break; } } } Loading Loading @@ -7207,11 +7290,10 @@ public class AudioService extends IAudioService.Stub // HDMI output removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI); } } checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, postUpdateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI, "HdmiPlaybackClient.DisplayStatusCallback"); } } private class MyHdmiControlStatusChangeListenerCallback implements HdmiControlManager.HdmiControlStatusChangeListener { Loading Loading
services/core/java/com/android/server/audio/AudioService.java +116 −34 Original line number Diff line number Diff line Loading @@ -285,6 +285,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_PLAYBACK_CONFIG_CHANGE = 29; private static final int MSG_BROADCAST_MICROPHONE_MUTE = 30; private static final int MSG_CHECK_MODE_FOR_UID = 31; private static final int MSG_STREAM_DEVICES_CHANGED = 32; private static final int MSG_UPDATE_VOLUME_STATES_FOR_DEVICE = 33; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) Loading Loading @@ -1283,7 +1285,6 @@ public class AudioService extends IAudioService.Stub } if (isPlatformTelevision()) { checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller); synchronized (mHdmiClientLock) { if (mHdmiManager != null && mHdmiPlaybackClient != null) { updateHdmiCecSinkLocked(mHdmiCecSink | false); Loading @@ -1303,9 +1304,50 @@ public class AudioService extends IAudioService.Stub } } private void checkAddAllFixedVolumeDevices(int device, String caller) { /** * Asynchronously update volume states for the given device. * * @param device a single audio device, ensure that this is not a devices bitmask * @param caller caller of this method */ private void postUpdateVolumeStatesForAudioDevice(int device, String caller) { sendMsg(mAudioHandler, MSG_UPDATE_VOLUME_STATES_FOR_DEVICE, SENDMSG_QUEUE, device /*arg1*/, 0 /*arg2*/, caller /*obj*/, 0 /*delay*/); } /** * Update volume states for the given device. * * This will initialize the volume index if no volume index is available. * If the device is the currently routed device, fixed/full volume policies will be applied. * * @param device a single audio device, ensure that this is not a devices bitmask * @param caller caller of this method */ private void onUpdateVolumeStatesForAudioDevice(int device, String caller) { final int numStreamTypes = AudioSystem.getNumStreamTypes(); synchronized (mSettingsLock) { synchronized (VolumeStreamState.class) { for (int streamType = 0; streamType < numStreamTypes; streamType++) { updateVolumeStates(device, streamType, caller); } } } } /** * Update volume states for the given device and given stream. * * This will initialize the volume index if no volume index is available. * If the device is the currently routed device, fixed/full volume policies will be applied. * * @param device a single audio device, ensure that this is not a devices bitmask * @param streamType streamType to be updated * @param caller caller of this method */ private void updateVolumeStates(int device, int streamType, String caller) { if (!mStreamStates[streamType].hasIndexForDevice(device)) { // set the default value, if device is affected by a full/fix/abs volume rule, it // will taken into account in checkFixedVolumeDevices() Loading @@ -1314,14 +1356,22 @@ public class AudioService extends IAudioService.Stub .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), device, caller, true /*hasModifyAudioSettings*/); } // Check if device to be updated is routed for the given audio stream List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt( new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build()); for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) { if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType( device)) { mStreamStates[streamType].checkFixedVolumeDevices(); // Unmute streams if device is full volume if (mFullVolumeDevices.contains(device)) { // Unmute streams if required and device is full volume if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) { mStreamStates[streamType].mute(false); } } } } private void checkAllFixedVolumeDevices() { Loading Loading @@ -1868,8 +1918,13 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */ public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); enforceModifyAudioRoutingPermission(); return getDevicesForAttributesInt(attributes); } protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); return AudioSystem.getDevicesForAttributes(attributes); } Loading Loading @@ -4912,11 +4967,21 @@ public class AudioService extends IAudioService.Stub } } private void observeDevicesForStreams(int skipStream) { private void onObserveDevicesForAllStreams(int skipStream) { synchronized (mSettingsLock) { synchronized (VolumeStreamState.class) { for (int stream = 0; stream < mStreamStates.length; stream++) { if (stream != skipStream) { mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/); int devices = mStreamStates[stream].observeDevicesForStream_syncVSS( false /*checkOthers*/); Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices); for (Integer device : devicesSet) { // Update volume states for devices routed for the stream updateVolumeStates(device, stream, "AudioService#onObserveDevicesForAllStreams"); } } } } } Loading @@ -4925,16 +4990,18 @@ public class AudioService extends IAudioService.Stub /** only public for mocking/spying, do not call outside of AudioService */ @VisibleForTesting public void postObserveDevicesForAllStreams() { postObserveDevicesForAllStreams(-1); } /** only public for mocking/spying, do not call outside of AudioService */ @VisibleForTesting public void postObserveDevicesForAllStreams(int skipStream) { sendMsg(mAudioHandler, MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS, SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/, SENDMSG_QUEUE, skipStream /*arg1*/, 0 /*arg2*/, null /*obj*/, 0 /*delay*/); } private void onObserveDevicesForAllStreams() { observeDevicesForStreams(-1); } /** * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int) * @param device the audio device to be affected Loading Loading @@ -4985,7 +5052,8 @@ public class AudioService extends IAudioService.Stub + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); postUpdateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); } /** Loading Loading @@ -5616,6 +5684,7 @@ public class AudioService extends IAudioService.Stub } } @GuardedBy("VolumeStreamState.class") public int observeDevicesForStream_syncVSS(boolean checkOthers) { if (!mSystemServer.isPrivileged()) { return AudioSystem.DEVICE_NONE; Loading @@ -5628,15 +5697,19 @@ public class AudioService extends IAudioService.Stub mObservedDevices = devices; if (checkOthers) { // one stream's devices have changed, check the others observeDevicesForStreams(mStreamType); postObserveDevicesForAllStreams(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)); // send STREAM_DEVICES_CHANGED_ACTION on the message handler so it is scheduled after // the postObserveDevicesForStreams is handled sendMsg(mAudioHandler, MSG_STREAM_DEVICES_CHANGED, SENDMSG_QUEUE, prevDevices /*arg1*/, devices /*arg2*/, // ok to send reference to this object, it is final mStreamDevicesChanged /*obj*/, 0 /*delay*/); return devices; } Loading Loading @@ -6408,7 +6481,7 @@ public class AudioService extends IAudioService.Stub break; case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS: onObserveDevicesForAllStreams(); onObserveDevicesForAllStreams(/*skipStream*/ msg.arg1); break; case MSG_HDMI_VOLUME_CHECK: Loading Loading @@ -6451,6 +6524,16 @@ public class AudioService extends IAudioService.Stub mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid())); } break; case MSG_STREAM_DEVICES_CHANGED: sendBroadcastToAll(((Intent) msg.obj) .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, msg.arg1) .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, msg.arg2)); break; case MSG_UPDATE_VOLUME_STATES_FOR_DEVICE: onUpdateVolumeStatesForAudioDevice(msg.arg1, (String) msg.obj); break; } } } Loading Loading @@ -7207,11 +7290,10 @@ public class AudioService extends IAudioService.Stub // HDMI output removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI); } } checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, postUpdateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI, "HdmiPlaybackClient.DisplayStatusCallback"); } } private class MyHdmiControlStatusChangeListenerCallback implements HdmiControlManager.HdmiControlStatusChangeListener { Loading