diff options
4 files changed, 130 insertions, 39 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index c573332235d8..4ce6d91d25b0 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -43,7 +43,6 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; -import java.util.ArrayList; /** @hide */ /*package*/ final class AudioDeviceBroker { @@ -376,24 +375,29 @@ import java.util.ArrayList; mAudioService.postAccessoryPlugMediaUnmute(device); } - /*package*/ AudioService.VolumeStreamState getStreamState(int streamType) { - return mAudioService.getStreamState(streamType); + /*package*/ int getVssVolumeForDevice(int streamType, int device) { + return mAudioService.getVssVolumeForDevice(streamType, device); } - /*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() { - return mAudioService.mSetModeDeathHandlers; + /*package*/ int getModeOwnerPid() { + return mAudioService.getModeOwnerPid(); } /*package*/ int getDeviceForStream(int streamType) { return mAudioService.getDeviceForStream(streamType); } - /*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) { - mAudioService.setDeviceVolume(streamState, device); + /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { + mAudioService.postApplyVolumeOnDevice(streamType, device, caller); } - /*packages*/ void observeDevicesForAllStreams() { - mAudioService.observeDevicesForAllStreams(); + /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, + String caller) { + mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); + } + + /*packages*/ void postObserveDevicesForAllStreams() { + mAudioService.postObserveDevicesForAllStreams(); } /*package*/ boolean isInCommunication() { diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 91b51b4989d8..f9dbdd5b13db 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -198,14 +198,10 @@ public final class AudioDeviceInventory { } } if (a2dpVolume != -1) { - AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); - // Convert index to internal representation in VolumeStreamState - a2dpVolume = a2dpVolume * 10; - streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - "onSetA2dpSinkConnectionState"); - mDeviceBroker.setDeviceVolume( - streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); + mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC, + // convert index to internal representation in VolumeStreamState + a2dpVolume * 10, + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState"); } makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice), "onSetA2dpSinkConnectionState", a2dpCodec); @@ -302,14 +298,11 @@ public final class AudioDeviceInventory { if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) { // Device is connected if (a2dpVolume != -1) { - final AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); - // Convert index to internal representation in VolumeStreamState - a2dpVolume = a2dpVolume * 10; - streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC, + // convert index to internal representation in VolumeStreamState + a2dpVolume * 10, + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onBluetoothA2dpActiveDeviceChange"); - mDeviceBroker.setDeviceVolume( - streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); } } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) { if (di.mDeviceCodecFormat != a2dpCodec) { @@ -352,7 +345,7 @@ public final class AudioDeviceInventory { } } mRoutesObservers.finishBroadcast(); - mDeviceBroker.observeDevicesForAllStreams(); + mDeviceBroker.postObserveDevicesForAllStreams(); } private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG = @@ -655,8 +648,6 @@ public final class AudioDeviceInventory { int a2dpCodec) { // enable A2DP before notifying A2DP connection to avoid unnecessary processing in // audio policy manager - AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec); @@ -727,8 +718,8 @@ public final class AudioDeviceInventory { @GuardedBy("mConnectedDevices") private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) { - final int hearingAidVolIndex = mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC) - .getIndex(AudioSystem.DEVICE_OUT_HEARING_AID); + final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC, + AudioSystem.DEVICE_OUT_HEARING_AID); mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, AudioSystem.STREAM_MUSIC); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID, @@ -739,9 +730,8 @@ public final class AudioDeviceInventory { new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT)); mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID); - mDeviceBroker.setDeviceVolume( - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC), - AudioSystem.DEVICE_OUT_HEARING_AID); + mDeviceBroker.postApplyVolumeOnDevice(AudioSystem.STREAM_MUSIC, + AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable"); setCurrentAudioRouteNameIfPossible(name); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d30a9d2b158e..ccce685ae060 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -258,6 +258,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23; private static final int MSG_ENABLE_SURROUND_FORMATS = 24; private static final int MSG_UPDATE_RINGER_MODE = 25; + private static final int MSG_SET_DEVICE_STREAM_VOLUME = 26; + private static final int MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS = 27; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) @@ -274,8 +276,8 @@ public class AudioService extends IAudioService.Stub /** @see VolumeStreamState */ private VolumeStreamState[] mStreamStates; - /*package*/ VolumeStreamState getStreamState(int stream) { - return mStreamStates[stream]; + /*package*/ int getVssVolumeForDevice(int stream, int device) { + return mStreamStates[stream].getIndex(device); } private SettingsObserver mSettingsObserver; @@ -2920,7 +2922,21 @@ public class AudioService extends IAudioService.Stub } - /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient { + /** + * Return the pid of the current audio mode owner + * @return 0 if nobody owns the mode + */ + /*package*/ int getModeOwnerPid() { + int modeOwnerPid = 0; + try { + modeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); + } catch (Exception e) { + // nothing to do, modeOwnerPid is not modified + } + return modeOwnerPid; + } + + private class SetModeDeathHandler implements IBinder.DeathRecipient { private IBinder mCb; // To be notified of client's death private int mPid; private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client @@ -4080,8 +4096,14 @@ public class AudioService extends IAudioService.Stub } } + /*package*/ void postObserveDevicesForAllStreams() { + sendMsg(mAudioHandler, + MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/, + 0 /*delay*/); + } - /*package*/ void observeDevicesForAllStreams() { + private void onObserveDevicesForAllStreams() { observeDevicesForStreams(-1); } @@ -4254,7 +4276,7 @@ public class AudioService extends IAudioService.Stub // 2 mSetModeLock // 3 mSettingsLock // 4 VolumeStreamState.class - public class VolumeStreamState { + private class VolumeStreamState { private final int mStreamType; private int mIndexMin; private int mIndexMax; @@ -4724,6 +4746,74 @@ public class AudioService extends IAudioService.Stub } } + private static final class DeviceVolumeUpdate { + final int mStreamType; + final int mDevice; + final @NonNull String mCaller; + private static final int NO_NEW_INDEX = -2049; + private final int mVssVolIndex; + + // Constructor with volume index, meant to cause this volume to be set and applied for the + // given stream type on the given device + DeviceVolumeUpdate(int streamType, int vssVolIndex, int device, @NonNull String caller) { + mStreamType = streamType; + mVssVolIndex = vssVolIndex; + mDevice = device; + mCaller = caller; + } + + // Constructor with no volume index, meant to cause re-apply of volume for the given + // stream type on the given device + DeviceVolumeUpdate(int streamType, int device, @NonNull String caller) { + mStreamType = streamType; + mVssVolIndex = NO_NEW_INDEX; + mDevice = device; + mCaller = caller; + } + + boolean hasVolumeIndex() { + return mVssVolIndex != NO_NEW_INDEX; + } + + int getVolumeIndex() throws IllegalStateException { + Preconditions.checkState(mVssVolIndex != NO_NEW_INDEX); + return mVssVolIndex; + } + } + + /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, + String caller) { + sendMsg(mAudioHandler, + MSG_SET_DEVICE_STREAM_VOLUME, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, + new DeviceVolumeUpdate(streamType, vssVolIndex, device, caller), + 0 /*delay*/); + } + + /*package*/ void postApplyVolumeOnDevice(int streamType, int device, @NonNull String caller) { + sendMsg(mAudioHandler, + MSG_SET_DEVICE_STREAM_VOLUME, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, + new DeviceVolumeUpdate(streamType, device, caller), + 0 /*delay*/); + } + + private void onSetVolumeIndexOnDevice(@NonNull DeviceVolumeUpdate update) { + synchronized (VolumeStreamState.class) { + final VolumeStreamState streamState = mStreamStates[update.mStreamType]; + if (update.hasVolumeIndex()) { + final int index = update.getVolumeIndex(); + streamState.setIndex(index, update.mDevice, update.mCaller); + sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x" + + Integer.toHexString(update.mDevice) + " volIdx:" + index)); + } else { + sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + + " update vol on dev:0x" + Integer.toHexString(update.mDevice))); + } + setDeviceVolume(streamState, update.mDevice); + } + } + /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) { final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported(); @@ -5164,6 +5254,14 @@ public class AudioService extends IAudioService.Stub case MSG_UPDATE_RINGER_MODE: onUpdateRingerModeServiceInt(); break; + + case MSG_SET_DEVICE_STREAM_VOLUME: + onSetVolumeIndexOnDevice((DeviceVolumeUpdate) msg.obj); + break; + + case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS: + onObserveDevicesForAllStreams(); + break; } } } diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 332ff362392a..068c3d8a1264 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -765,8 +765,7 @@ public class BtHelper { broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); // Accept SCO audio activation only in NORMAL audio mode or if the mode is // currently controlled by the same client process. - int modeOwnerPid = mDeviceBroker.getSetModeDeathHandlers().isEmpty() - ? 0 : mDeviceBroker.getSetModeDeathHandlers().get(0).getPid(); + final int modeOwnerPid = mDeviceBroker.getModeOwnerPid(); if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) { Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid " + modeOwnerPid + " != creatorPid " + mCreatorPid); |