AudioService: async volume updates from DeviceInventory
Make VolumeStreamState private to AudioService, and don't let AudioDeviceBroker, AudioDeviceInventory manipulate it. Only let them post messages on AudioService message handler to access them. Refactor methods to set a volume index and observe devices from AudioDeviceInventory to AudioService to be asynchronous. Bug: 130686447 Bug: 129163231 Test: verify volume is last used when connecting A2DP or hearing aid Change-Id: I356af79213f4c21ed4ebaf86922fbbd9bf48a892
This commit is contained in:
@@ -43,7 +43,6 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
/*package*/ final class AudioDeviceBroker {
|
/*package*/ final class AudioDeviceBroker {
|
||||||
@@ -376,24 +375,29 @@ import java.util.ArrayList;
|
|||||||
mAudioService.postAccessoryPlugMediaUnmute(device);
|
mAudioService.postAccessoryPlugMediaUnmute(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ AudioService.VolumeStreamState getStreamState(int streamType) {
|
/*package*/ int getVssVolumeForDevice(int streamType, int device) {
|
||||||
return mAudioService.getStreamState(streamType);
|
return mAudioService.getVssVolumeForDevice(streamType, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() {
|
/*package*/ int getModeOwnerPid() {
|
||||||
return mAudioService.mSetModeDeathHandlers;
|
return mAudioService.getModeOwnerPid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getDeviceForStream(int streamType) {
|
/*package*/ int getDeviceForStream(int streamType) {
|
||||||
return mAudioService.getDeviceForStream(streamType);
|
return mAudioService.getDeviceForStream(streamType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) {
|
/*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) {
|
||||||
mAudioService.setDeviceVolume(streamState, device);
|
mAudioService.postApplyVolumeOnDevice(streamType, device, caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*packages*/ void observeDevicesForAllStreams() {
|
/*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
|
||||||
mAudioService.observeDevicesForAllStreams();
|
String caller) {
|
||||||
|
mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*packages*/ void postObserveDevicesForAllStreams() {
|
||||||
|
mAudioService.postObserveDevicesForAllStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ boolean isInCommunication() {
|
/*package*/ boolean isInCommunication() {
|
||||||
|
|||||||
@@ -198,14 +198,10 @@ public final class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (a2dpVolume != -1) {
|
if (a2dpVolume != -1) {
|
||||||
AudioService.VolumeStreamState streamState =
|
mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
|
||||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
|
// convert index to internal representation in VolumeStreamState
|
||||||
// Convert index to internal representation in VolumeStreamState
|
a2dpVolume * 10,
|
||||||
a2dpVolume = a2dpVolume * 10;
|
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
|
||||||
streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
|
||||||
"onSetA2dpSinkConnectionState");
|
|
||||||
mDeviceBroker.setDeviceVolume(
|
|
||||||
streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
|
|
||||||
}
|
}
|
||||||
makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
|
makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
|
||||||
"onSetA2dpSinkConnectionState", a2dpCodec);
|
"onSetA2dpSinkConnectionState", a2dpCodec);
|
||||||
@@ -302,14 +298,11 @@ public final class AudioDeviceInventory {
|
|||||||
if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
|
if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
|
||||||
// Device is connected
|
// Device is connected
|
||||||
if (a2dpVolume != -1) {
|
if (a2dpVolume != -1) {
|
||||||
final AudioService.VolumeStreamState streamState =
|
mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
|
||||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
|
// convert index to internal representation in VolumeStreamState
|
||||||
// Convert index to internal representation in VolumeStreamState
|
a2dpVolume * 10,
|
||||||
a2dpVolume = a2dpVolume * 10;
|
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||||
streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
|
||||||
"onBluetoothA2dpActiveDeviceChange");
|
"onBluetoothA2dpActiveDeviceChange");
|
||||||
mDeviceBroker.setDeviceVolume(
|
|
||||||
streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
|
|
||||||
}
|
}
|
||||||
} else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
|
} else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
|
||||||
if (di.mDeviceCodecFormat != a2dpCodec) {
|
if (di.mDeviceCodecFormat != a2dpCodec) {
|
||||||
@@ -352,7 +345,7 @@ public final class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mRoutesObservers.finishBroadcast();
|
mRoutesObservers.finishBroadcast();
|
||||||
mDeviceBroker.observeDevicesForAllStreams();
|
mDeviceBroker.postObserveDevicesForAllStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
|
private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
|
||||||
@@ -655,8 +648,6 @@ public final class AudioDeviceInventory {
|
|||||||
int a2dpCodec) {
|
int a2dpCodec) {
|
||||||
// enable A2DP before notifying A2DP connection to avoid unnecessary processing in
|
// enable A2DP before notifying A2DP connection to avoid unnecessary processing in
|
||||||
// audio policy manager
|
// audio policy manager
|
||||||
AudioService.VolumeStreamState streamState =
|
|
||||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
|
|
||||||
mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource);
|
mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource);
|
||||||
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
|
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
|
||||||
@@ -727,8 +718,8 @@ public final class AudioDeviceInventory {
|
|||||||
|
|
||||||
@GuardedBy("mConnectedDevices")
|
@GuardedBy("mConnectedDevices")
|
||||||
private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
|
private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
|
||||||
final int hearingAidVolIndex = mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC)
|
final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
|
||||||
.getIndex(AudioSystem.DEVICE_OUT_HEARING_AID);
|
AudioSystem.DEVICE_OUT_HEARING_AID);
|
||||||
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, AudioSystem.STREAM_MUSIC);
|
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, AudioSystem.STREAM_MUSIC);
|
||||||
|
|
||||||
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
|
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
|
||||||
@@ -739,9 +730,8 @@ public final class AudioDeviceInventory {
|
|||||||
new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name,
|
new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name,
|
||||||
address, AudioSystem.AUDIO_FORMAT_DEFAULT));
|
address, AudioSystem.AUDIO_FORMAT_DEFAULT));
|
||||||
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID);
|
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID);
|
||||||
mDeviceBroker.setDeviceVolume(
|
mDeviceBroker.postApplyVolumeOnDevice(AudioSystem.STREAM_MUSIC,
|
||||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC),
|
AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable");
|
||||||
AudioSystem.DEVICE_OUT_HEARING_AID);
|
|
||||||
setCurrentAudioRouteNameIfPossible(name);
|
setCurrentAudioRouteNameIfPossible(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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_DISPATCH_AUDIO_SERVER_STATE = 23;
|
||||||
private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
|
private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
|
||||||
private static final int MSG_UPDATE_RINGER_MODE = 25;
|
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
|
// start of messages handled under wakelock
|
||||||
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
|
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
|
||||||
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
|
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
|
||||||
@@ -274,8 +276,8 @@ public class AudioService extends IAudioService.Stub
|
|||||||
/** @see VolumeStreamState */
|
/** @see VolumeStreamState */
|
||||||
private VolumeStreamState[] mStreamStates;
|
private VolumeStreamState[] mStreamStates;
|
||||||
|
|
||||||
/*package*/ VolumeStreamState getStreamState(int stream) {
|
/*package*/ int getVssVolumeForDevice(int stream, int device) {
|
||||||
return mStreamStates[stream];
|
return mStreamStates[stream].getIndex(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SettingsObserver mSettingsObserver;
|
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 IBinder mCb; // To be notified of client's death
|
||||||
private int mPid;
|
private int mPid;
|
||||||
private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
|
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);
|
observeDevicesForStreams(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4254,7 +4276,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
// 2 mSetModeLock
|
// 2 mSetModeLock
|
||||||
// 3 mSettingsLock
|
// 3 mSettingsLock
|
||||||
// 4 VolumeStreamState.class
|
// 4 VolumeStreamState.class
|
||||||
public class VolumeStreamState {
|
private class VolumeStreamState {
|
||||||
private final int mStreamType;
|
private final int mStreamType;
|
||||||
private int mIndexMin;
|
private int mIndexMin;
|
||||||
private int mIndexMax;
|
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) {
|
/*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
|
||||||
|
|
||||||
final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
|
final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
|
||||||
@@ -5164,6 +5254,14 @@ public class AudioService extends IAudioService.Stub
|
|||||||
case MSG_UPDATE_RINGER_MODE:
|
case MSG_UPDATE_RINGER_MODE:
|
||||||
onUpdateRingerModeServiceInt();
|
onUpdateRingerModeServiceInt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSG_SET_DEVICE_STREAM_VOLUME:
|
||||||
|
onSetVolumeIndexOnDevice((DeviceVolumeUpdate) msg.obj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS:
|
||||||
|
onObserveDevicesForAllStreams();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -765,8 +765,7 @@ public class BtHelper {
|
|||||||
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
|
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
|
||||||
// Accept SCO audio activation only in NORMAL audio mode or if the mode is
|
// Accept SCO audio activation only in NORMAL audio mode or if the mode is
|
||||||
// currently controlled by the same client process.
|
// currently controlled by the same client process.
|
||||||
int modeOwnerPid = mDeviceBroker.getSetModeDeathHandlers().isEmpty()
|
final int modeOwnerPid = mDeviceBroker.getModeOwnerPid();
|
||||||
? 0 : mDeviceBroker.getSetModeDeathHandlers().get(0).getPid();
|
|
||||||
if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) {
|
if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) {
|
||||||
Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid "
|
Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid "
|
||||||
+ modeOwnerPid + " != creatorPid " + mCreatorPid);
|
+ modeOwnerPid + " != creatorPid " + mCreatorPid);
|
||||||
|
|||||||
Reference in New Issue
Block a user