Merge "AudioService: fix communication device APIs" into tm-qpr-dev

This commit is contained in:
Eric Laurent
2023-01-26 20:11:45 +00:00
committed by Android (Google) Code Review
2 changed files with 84 additions and 46 deletions

View File

@@ -56,6 +56,7 @@ import android.util.PrintWriterPrinter;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
@@ -434,6 +435,48 @@ import java.util.concurrent.atomic.AtomicBoolean;
return device; 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. * Returns the device currently requested for communication use case.
* @return AudioDeviceInfo the requested device for communication. * @return AudioDeviceInfo the requested device for communication.
@@ -441,7 +484,29 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* package */ AudioDeviceInfo getCommunicationDevice() { /* package */ AudioDeviceInfo getCommunicationDevice() {
synchronized (mDeviceStateLock) { synchronized (mDeviceStateLock) {
updateActiveCommunicationDevice(); 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;
} }
} }
@@ -918,8 +983,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
@GuardedBy("mDeviceStateLock") @GuardedBy("mDeviceStateLock")
private void dispatchCommunicationDevice() { private void dispatchCommunicationDevice() {
int portId = (mActiveCommunicationDevice == null) ? 0 AudioDeviceInfo device = getCommunicationDevice();
: mActiveCommunicationDevice.getId(); int portId = device != null ? device.getId() : 0;
if (portId == mCurCommunicationPortId) { if (portId == mCurCommunicationPortId) {
return; return;
} }
@@ -936,6 +1001,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
mCommDevDispatchers.finishBroadcast(); mCommDevDispatchers.finishBroadcast();
} }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Communication with (to) AudioService // Communication with (to) AudioService
//TODO check whether the AudioService methods are candidates to move here //TODO check whether the AudioService methods are candidates to move here

View File

@@ -5846,46 +5846,16 @@ public class AudioService extends IAudioService.Stub
restoreDeviceVolumeBehavior(); 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) {
for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
if (device.getType() == type) {
return true;
}
}
return false;
}
/** @see AudioManager#getAvailableCommunicationDevices(int) */ /** @see AudioManager#getAvailableCommunicationDevices(int) */
public int[] getAvailableCommunicationDeviceIds() { public int[] getAvailableCommunicationDeviceIds() {
ArrayList<Integer> deviceIds = new ArrayList<>(); List<AudioDeviceInfo> commDevices = AudioDeviceBroker.getAvailableCommunicationDevices();
AudioDeviceInfo[] devices = AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); return commDevices.stream().mapToInt(AudioDeviceInfo::getId).toArray();
for (AudioDeviceInfo device : devices) {
if (isValidCommunicationDevice(device)) {
deviceIds.add(device.getId());
}
}
return deviceIds.stream().mapToInt(Integer::intValue).toArray();
} }
/**
* @see AudioManager#setCommunicationDevice(int) /**
* @see AudioManager#clearCommunicationDevice() * @see AudioManager#setCommunicationDevice(int)
*/ * @see AudioManager#clearCommunicationDevice()
*/
public boolean setCommunicationDevice(IBinder cb, int portId) { public boolean setCommunicationDevice(IBinder cb, int portId) {
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid(); final int pid = Binder.getCallingPid();
@@ -5897,7 +5867,7 @@ public class AudioService extends IAudioService.Stub
Log.w(TAG, "setCommunicationDevice: invalid portID " + portId); Log.w(TAG, "setCommunicationDevice: invalid portID " + portId);
return false; return false;
} }
if (!isValidCommunicationDevice(device)) { if (!AudioDeviceBroker.isValidCommunicationDevice(device)) {
throw new IllegalArgumentException("invalid device type " + device.getType()); throw new IllegalArgumentException("invalid device type " + device.getType());
} }
} }
@@ -5940,13 +5910,15 @@ public class AudioService extends IAudioService.Stub
/** @see AudioManager#getCommunicationDevice() */ /** @see AudioManager#getCommunicationDevice() */
public int getCommunicationDevice() { public int getCommunicationDevice() {
int deviceId = 0;
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
AudioDeviceInfo device = mDeviceBroker.getCommunicationDevice(); try {
Binder.restoreCallingIdentity(ident); AudioDeviceInfo device = mDeviceBroker.getCommunicationDevice();
if (device == null) { deviceId = device != null ? device.getId() : 0;
return 0; } finally {
Binder.restoreCallingIdentity(ident);
} }
return device.getId(); return deviceId;
} }
/** @see AudioManager#addOnCommunicationDeviceChangedListener( /** @see AudioManager#addOnCommunicationDeviceChangedListener(