Merge "AudioService: fix communication device APIs"

This commit is contained in:
Eric Laurent
2023-01-26 17:15:53 +00:00
committed by Android (Google) Code Review
2 changed files with 81 additions and 50 deletions

View File

@@ -58,6 +58,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
@@ -453,6 +454,48 @@ import java.util.concurrent.atomic.AtomicBoolean;
return device;
}
private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
AudioDeviceInfo.TYPE_WIRED_HEADSET,
AudioDeviceInfo.TYPE_USB_HEADSET,
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
AudioDeviceInfo.TYPE_HEARING_AID,
AudioDeviceInfo.TYPE_BLE_HEADSET,
AudioDeviceInfo.TYPE_USB_DEVICE,
AudioDeviceInfo.TYPE_BLE_SPEAKER,
AudioDeviceInfo.TYPE_LINE_ANALOG,
AudioDeviceInfo.TYPE_HDMI,
AudioDeviceInfo.TYPE_AUX_LINE
};
/*package */ static boolean isValidCommunicationDevice(AudioDeviceInfo device) {
for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
if (device.getType() == type) {
return true;
}
}
return false;
}
/* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() {
ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>();
AudioDeviceInfo[] allDevices =
AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo device : allDevices) {
if (isValidCommunicationDevice(device)) {
commDevices.add(device);
}
}
return commDevices;
}
private @Nullable AudioDeviceInfo getCommunicationDeviceOfType(int type) {
return getAvailableCommunicationDevices().stream().filter(d -> d.getType() == type)
.findFirst().orElse(null);
}
/**
* Returns the device currently requested for communication use case.
* @return AudioDeviceInfo the requested device for communication.
@@ -460,7 +503,29 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* package */ AudioDeviceInfo getCommunicationDevice() {
synchronized (mDeviceStateLock) {
updateActiveCommunicationDevice();
return mActiveCommunicationDevice;
AudioDeviceInfo device = mActiveCommunicationDevice;
// make sure we return a valid communication device (i.e. a device that is allowed by
// setCommunicationDevice()) for consistency.
if (device != null) {
// a digital dock is used instead of the speaker in speakerphone mode and should
// be reflected as such
if (device.getType() == AudioDeviceInfo.TYPE_DOCK) {
device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
}
// Try to default to earpiece when current communication device is not valid. This can
// happen for instance if no call is active. If no earpiece device is available take the
// first valid communication device
if (device == null || !AudioDeviceBroker.isValidCommunicationDevice(device)) {
device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
if (device == null) {
List<AudioDeviceInfo> commDevices = getAvailableCommunicationDevices();
if (!commDevices.isEmpty()) {
device = commDevices.get(0);
}
}
}
return device;
}
}
@@ -942,8 +1007,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
@GuardedBy("mDeviceStateLock")
private void dispatchCommunicationDevice() {
int portId = (mActiveCommunicationDevice == null) ? 0
: mActiveCommunicationDevice.getId();
AudioDeviceInfo device = getCommunicationDevice();
int portId = device != null ? device.getId() : 0;
if (portId == mCurCommunicationPortId) {
return;
}
@@ -960,6 +1025,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
mCommDevDispatchers.finishBroadcast();
}
//---------------------------------------------------------------------
// Communication with (to) AudioService
//TODO check whether the AudioService methods are candidates to move here

View File

@@ -6067,49 +6067,16 @@ public class AudioService extends IAudioService.Stub
restoreDeviceVolumeBehavior();
}
private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
AudioDeviceInfo.TYPE_WIRED_HEADSET,
AudioDeviceInfo.TYPE_USB_HEADSET,
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
AudioDeviceInfo.TYPE_HEARING_AID,
AudioDeviceInfo.TYPE_BLE_HEADSET,
AudioDeviceInfo.TYPE_USB_DEVICE,
AudioDeviceInfo.TYPE_BLE_SPEAKER,
AudioDeviceInfo.TYPE_LINE_ANALOG,
AudioDeviceInfo.TYPE_HDMI,
AudioDeviceInfo.TYPE_AUX_LINE
};
private boolean isValidCommunicationDevice(AudioDeviceInfo device) {
if (!device.isSink()) {
return false;
}
for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
if (device.getType() == type) {
return true;
}
}
return false;
}
/** @see AudioManager#getAvailableCommunicationDevices(int) */
public int[] getAvailableCommunicationDeviceIds() {
ArrayList<Integer> deviceIds = new ArrayList<>();
AudioDeviceInfo[] devices = AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo device : devices) {
if (isValidCommunicationDevice(device)) {
deviceIds.add(device.getId());
}
}
return deviceIds.stream().mapToInt(Integer::intValue).toArray();
List<AudioDeviceInfo> commDevices = AudioDeviceBroker.getAvailableCommunicationDevices();
return commDevices.stream().mapToInt(AudioDeviceInfo::getId).toArray();
}
/**
* @see AudioManager#setCommunicationDevice(int)
* @see AudioManager#clearCommunicationDevice()
*/
/**
* @see AudioManager#setCommunicationDevice(int)
* @see AudioManager#clearCommunicationDevice()
*/
public boolean setCommunicationDevice(IBinder cb, int portId) {
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -6121,7 +6088,7 @@ public class AudioService extends IAudioService.Stub
Log.w(TAG, "setCommunicationDevice: invalid portID " + portId);
return false;
}
if (!isValidCommunicationDevice(device)) {
if (!AudioDeviceBroker.isValidCommunicationDevice(device)) {
if (!device.isSink()) {
throw new IllegalArgumentException("device must have sink role");
} else {
@@ -6169,17 +6136,15 @@ public class AudioService extends IAudioService.Stub
/** @see AudioManager#getCommunicationDevice() */
public int getCommunicationDevice() {
AudioDeviceInfo device = null;
int deviceId = 0;
final long ident = Binder.clearCallingIdentity();
try {
device = mDeviceBroker.getCommunicationDevice();
AudioDeviceInfo device = mDeviceBroker.getCommunicationDevice();
deviceId = device != null ? device.getId() : 0;
} finally {
Binder.restoreCallingIdentity(ident);
}
if (device == null) {
return 0;
}
return device.getId();
return deviceId;
}
/** @see AudioManager#addOnCommunicationDeviceChangedListener(