summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2023-05-02 07:20:27 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-05-02 07:20:27 +0000
commit6a9342d76fb7ed0d315720cd5d97d98da113c86b (patch)
tree7a8d9766e390b911d668361366c9164187b48b87
parenta9a21d4bf659bdec88e35cba0536fd1fcc81bf90 (diff)
parentced3c22d90d579663199d57c0de5310c674c6a8f (diff)
Merge "AudioDeviceInventory: add cache for preferred device roles" into udc-dev
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java24
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java336
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java15
3 files changed, 327 insertions, 48 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index ada92f5545c2..c879fa64ff02 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1092,21 +1092,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
+ return mDeviceInventory.setPreferredDevicesForStrategyAndSave(strategy, devices);
}
/*package*/ int removePreferredDevicesForStrategySync(int strategy) {
- return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
+ return mDeviceInventory.removePreferredDevicesForStrategyAndSave(strategy);
}
/*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy,
@NonNull AudioDeviceAttributes device) {
- return mDeviceInventory.setDeviceAsNonDefaultForStrategySync(strategy, device);
+ return mDeviceInventory.setDeviceAsNonDefaultForStrategyAndSave(strategy, device);
}
/*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy,
@NonNull AudioDeviceAttributes device) {
- return mDeviceInventory.removeDeviceAsNonDefaultForStrategySync(strategy, device);
+ return mDeviceInventory.removeDeviceAsNonDefaultForStrategyAndSave(strategy, device);
}
/*package*/ void registerStrategyPreferredDevicesDispatcher(
@@ -1131,11 +1131,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset,
@NonNull List<AudioDeviceAttributes> devices) {
- return mDeviceInventory.setPreferredDevicesForCapturePresetSync(capturePreset, devices);
+ return mDeviceInventory.setPreferredDevicesForCapturePresetAndSave(capturePreset, devices);
}
/*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
- return mDeviceInventory.clearPreferredDevicesForCapturePresetSync(capturePreset);
+ return mDeviceInventory.clearPreferredDevicesForCapturePresetAndSave(capturePreset);
}
/*package*/ void registerCapturePresetDevicesRoleDispatcher(
@@ -2165,18 +2165,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (preferredCommunicationDevice == null) {
AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
if (defaultDevice != null) {
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mCommunicationStrategyId, Arrays.asList(defaultDevice));
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mAccessibilityStrategyId, Arrays.asList(defaultDevice));
} else {
- removePreferredDevicesForStrategySync(mCommunicationStrategyId);
- removePreferredDevicesForStrategySync(mAccessibilityStrategyId);
+ mDeviceInventory.removePreferredDevicesForStrategy(mCommunicationStrategyId);
+ mDeviceInventory.removePreferredDevicesForStrategy(mAccessibilityStrategyId);
}
} else {
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice));
}
onUpdatePhoneStrategyDevice(preferredCommunicationDevice);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 228bc87cc20b..94d796bff609 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -43,6 +43,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -51,9 +52,12 @@ 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.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -176,14 +180,18 @@ public class AudioDeviceInventory {
new RemoteCallbackList<ICapturePresetDevicesRoleDispatcher>();
/*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
- mDeviceBroker = broker;
- mAudioSystem = AudioSystemAdapter.getDefaultAdapter();
+ this(broker, AudioSystemAdapter.getDefaultAdapter());
}
//-----------------------------------------------------------
/** for mocking only, allows to inject AudioSystem adapter */
/*package*/ AudioDeviceInventory(@NonNull AudioSystemAdapter audioSystem) {
- mDeviceBroker = null;
+ this(null, audioSystem);
+ }
+
+ private AudioDeviceInventory(@Nullable AudioDeviceBroker broker,
+ @Nullable AudioSystemAdapter audioSystem) {
+ mDeviceBroker = broker;
mAudioSystem = audioSystem;
}
@@ -276,9 +284,18 @@ public class AudioDeviceInventory {
pw.println(" " + prefix + " type:0x" + Integer.toHexString(keyType)
+ " (" + AudioSystem.getDeviceName(keyType)
+ ") addr:" + valueAddress); });
+ pw.println("\n" + prefix + "Preferred devices for capture preset:");
mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
pw.println(" " + prefix + "capturePreset:" + capturePreset
+ " devices:" + devices); });
+ pw.println("\n" + prefix + "Applied devices roles for strategies:");
+ mAppliedStrategyRoles.forEach((key, devices) -> {
+ pw.println(" " + prefix + "strategy: " + key.first
+ + " role:" + key.second + " devices:" + devices); });
+ pw.println("\n" + prefix + "Applied devices roles for presets:");
+ mAppliedPresetRoles.forEach((key, devices) -> {
+ pw.println(" " + prefix + "preset: " + key.first
+ + " role:" + key.second + " devices:" + devices); });
}
//------------------------------------------------------------
@@ -299,15 +316,15 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_STATE_AVAILABLE,
di.mDeviceCodecFormat);
}
+ mAppliedStrategyRoles.clear();
}
synchronized (mPreferredDevices) {
mPreferredDevices.forEach((strategy, devices) -> {
- mAudioSystem.setDevicesRoleForStrategy(
- strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices); });
+ setPreferredDevicesForStrategy(strategy, devices); });
}
synchronized (mNonDefaultDevices) {
mNonDefaultDevices.forEach((strategy, devices) -> {
- mAudioSystem.setDevicesRoleForStrategy(
+ addDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices); });
}
synchronized (mPreferredDevicesForCapturePreset) {
@@ -710,43 +727,51 @@ public class AudioDeviceInventory {
//------------------------------------------------------------
// preferred/non-default device(s)
- /*package*/ int setPreferredDevicesForStrategySync(int strategy,
+ /*package*/ int setPreferredDevicesForStrategyAndSave(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
+ final int status = setPreferredDevicesForStrategy(strategy, devices);
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveSetPreferredDevicesForStrategy(strategy, devices);
+ }
+ return status;
+ }
+ /*package*/ int setPreferredDevicesForStrategy(int strategy,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "setPreferredDevicesForStrategySync, strategy: " + strategy
+ "setPreferredDevicesForStrategy, strategy: " + strategy
+ " devices: " + devices)).printLog(TAG));
- status = mAudioSystem.setDevicesRoleForStrategy(
+ status = setDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
}
+ return status;
+ }
+ /*package*/ int removePreferredDevicesForStrategyAndSave(int strategy) {
+ final int status = removePreferredDevicesForStrategy(strategy);
if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForStrategy(strategy, devices);
+ mDeviceBroker.postSaveRemovePreferredDevicesForStrategy(strategy);
}
return status;
}
- /*package*/ int removePreferredDevicesForStrategySync(int strategy) {
+ /*package*/ int removePreferredDevicesForStrategy(int strategy) {
int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "removePreferredDevicesForStrategySync, strategy: "
+ "removePreferredDevicesForStrategy, strategy: "
+ strategy)).printLog(TAG));
- status = mAudioSystem.clearDevicesRoleForStrategy(
+ status = clearDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED);
}
-
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveRemovePreferredDevicesForStrategy(strategy);
- }
return status;
}
- /*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy,
+ /*package*/ int setDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
@@ -755,9 +780,9 @@ public class AudioDeviceInventory {
devices.add(device);
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "setDeviceAsNonDefaultForStrategySync, strategy: " + strategy
+ "setDeviceAsNonDefaultForStrategyAndSave, strategy: " + strategy
+ " device: " + device)).printLog(TAG));
- status = mAudioSystem.setDevicesRoleForStrategy(
+ status = addDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices);
}
@@ -767,7 +792,7 @@ public class AudioDeviceInventory {
return status;
}
- /*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy,
+ /*package*/ int removeDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
@@ -776,10 +801,10 @@ public class AudioDeviceInventory {
devices.add(device);
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "removeDeviceAsNonDefaultForStrategySync, strategy: "
+ "removeDeviceAsNonDefaultForStrategyAndSave, strategy: "
+ strategy + " devices: " + device)).printLog(TAG));
- status = mAudioSystem.removeDevicesRoleForStrategy(
+ status = removeDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices);
}
@@ -810,35 +835,72 @@ public class AudioDeviceInventory {
mNonDefDevDispatchers.unregister(dispatcher);
}
- /*package*/ int setPreferredDevicesForCapturePresetSync(
+ /*package*/ int setPreferredDevicesForCapturePresetAndSave(
int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
+ final int status = setPreferredDevicesForCapturePreset(capturePreset, devices);
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ }
+ return status;
+ }
+ private int setPreferredDevicesForCapturePreset(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
+ int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = mAudioSystem.setDevicesRoleForCapturePreset(
+ status = setDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
}
+ return status;
+ }
+ /*package*/ int clearPreferredDevicesForCapturePresetAndSave(int capturePreset) {
+ final int status = clearPreferredDevicesForCapturePreset(capturePreset);
if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
}
return status;
}
- /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
+ private int clearPreferredDevicesForCapturePreset(int capturePreset) {
int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = mAudioSystem.clearDevicesRoleForCapturePreset(
+ status = clearDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED);
}
-
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
- }
return status;
}
+ private int addDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return addDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.addDevicesRoleForCapturePreset(p, r, d);
+ }, capturePreset, role, devices);
+ }
+
+ private int removeDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return removeDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d);
+ }, capturePreset, role, devices);
+ }
+
+ private int setDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return setDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.addDevicesRoleForCapturePreset(p, r, d);
+ }, (p, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForCapturePreset(p, r);
+ }, capturePreset, role, devices);
+ }
+
+ private int clearDevicesRoleForCapturePreset(int capturePreset, int role) {
+ return clearDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForCapturePreset(p, r);
+ }, capturePreset, role);
+ }
+
/*package*/ void registerCapturePresetDevicesRoleDispatcher(
@NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
mDevRoleCapturePresetDispatchers.register(dispatcher);
@@ -849,7 +911,208 @@ public class AudioDeviceInventory {
mDevRoleCapturePresetDispatchers.unregister(dispatcher);
}
- //-----------------------------------------------------------------------
+ private int addDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return addDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.setDevicesRoleForStrategy(s, r, d);
+ }, strategy, role, devices);
+ }
+
+ private int removeDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return removeDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForStrategy(s, r, d);
+ }, strategy, role, devices);
+ }
+
+ private int setDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return setDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.setDevicesRoleForStrategy(s, r, d);
+ }, (s, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForStrategy(s, r);
+ }, strategy, role, devices);
+ }
+
+ private int clearDevicesRoleForStrategy(int strategy, int role) {
+ return clearDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForStrategy(s, r);
+ }, strategy, role);
+ }
+
+ //------------------------------------------------------------
+ // Cache for applied roles for strategies and devices. The cache avoids reapplying the
+ // same list of devices for a given role and strategy and the corresponding systematic
+ // redundant work in audio policy manager and audio flinger.
+ // The key is the pair <Strategy , Role> and the value is the current list of devices.
+
+ private final ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>>
+ mAppliedStrategyRoles = new ArrayMap<>();
+
+ // Cache for applied roles for capture presets and devices. The cache avoids reapplying the
+ // same list of devices for a given role and capture preset and the corresponding systematic
+ // redundant work in audio policy manager and audio flinger.
+ // The key is the pair <Preset , Role> and the value is the current list of devices.
+ private final ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>>
+ mAppliedPresetRoles = new ArrayMap<>();
+
+ interface AudioSystemInterface {
+ int deviceRoleAction(int usecase, int role, @Nullable List<AudioDeviceAttributes> devices);
+ }
+
+ private int addDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ List<AudioDeviceAttributes> roleDevices = new ArrayList<>();
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+
+ if (rolesMap.containsKey(key)) {
+ roleDevices = rolesMap.get(key);
+ for (AudioDeviceAttributes device : devices) {
+ if (!roleDevices.contains(device)) {
+ appliedDevices.add(device);
+ }
+ }
+ } else {
+ appliedDevices.addAll(devices);
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.addAll(appliedDevices);
+ rolesMap.put(key, roleDevices);
+ }
+ return status;
+ }
+ }
+
+ private int removeDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ if (!rolesMap.containsKey(key)) {
+ return AudioSystem.SUCCESS;
+ }
+ List<AudioDeviceAttributes> roleDevices = rolesMap.get(key);
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+ for (AudioDeviceAttributes device : devices) {
+ if (roleDevices.contains(device)) {
+ appliedDevices.add(device);
+ }
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.removeAll(appliedDevices);
+ if (roleDevices.isEmpty()) {
+ rolesMap.remove(key);
+ } else {
+ rolesMap.put(key, roleDevices);
+ }
+ }
+ return status;
+ }
+ }
+
+ private int setDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface addOp,
+ AudioSystemInterface clearOp,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ List<AudioDeviceAttributes> roleDevices = new ArrayList<>();
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+
+ if (rolesMap.containsKey(key)) {
+ roleDevices = rolesMap.get(key);
+ boolean equal = false;
+ if (roleDevices.size() == devices.size()) {
+ roleDevices.retainAll(devices);
+ equal = roleDevices.size() == devices.size();
+ }
+ if (!equal) {
+ clearOp.deviceRoleAction(useCase, role, null);
+ roleDevices.clear();
+ appliedDevices.addAll(devices);
+ }
+ } else {
+ appliedDevices.addAll(devices);
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = addOp.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.addAll(appliedDevices);
+ rolesMap.put(key, roleDevices);
+ }
+ return status;
+ }
+ }
+
+ private int clearDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi, int useCase, int role) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ if (!rolesMap.containsKey(key)) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, null);
+ if (status == AudioSystem.SUCCESS) {
+ rolesMap.remove(key);
+ }
+ return status;
+ }
+ }
+
+ @GuardedBy("mDevicesLock")
+ private void purgeDevicesRoles_l() {
+ purgeRoles(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForStrategy(s, r, d); });
+ purgeRoles(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d); });
+ }
+
+ @GuardedBy("mDevicesLock")
+ private void purgeRoles(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi) {
+ synchronized (rolesMap) {
+ Iterator<Map.Entry<Pair<Integer, Integer>, List<AudioDeviceAttributes>>> itRole =
+ rolesMap.entrySet().iterator();
+ while (itRole.hasNext()) {
+ Map.Entry<Pair<Integer, Integer>, List<AudioDeviceAttributes>> entry =
+ itRole.next();
+ Pair<Integer, Integer> keyRole = entry.getKey();
+ Iterator<AudioDeviceAttributes> itDev = rolesMap.get(keyRole).iterator();
+ while (itDev.hasNext()) {
+ AudioDeviceAttributes ada = itDev.next();
+ final String devKey = DeviceInfo.makeDeviceListKey(ada.getInternalType(),
+ ada.getAddress());
+ if (mConnectedDevices.get(devKey) == null) {
+ asi.deviceRoleAction(keyRole.first, keyRole.second, Arrays.asList(ada));
+ itDev.remove();
+ }
+ }
+ if (rolesMap.get(keyRole).isEmpty()) {
+ itRole.remove();
+ }
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------
/**
* Check if a device is in the list of connected devices
@@ -926,6 +1189,7 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
// always remove even if disconnection failed
mConnectedDevices.remove(deviceKey);
+ purgeDevicesRoles_l();
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
return true;
}
@@ -1231,6 +1495,7 @@ public class AudioDeviceInventory {
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null, true /*fromA2dp*/);
mmi.record();
+ purgeDevicesRoles_l();
}
@GuardedBy("mDevicesLock")
@@ -1404,6 +1669,7 @@ public class AudioDeviceInventory {
}
setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
+ purgeDevicesRoles_l();
}
@GuardedBy("mDevicesLock")
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index d066340c42b2..43438942a060 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -445,7 +445,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
- * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int, int[], String[])}
+ * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int, List)}
* @param capturePreset
* @param role
* @param devicesToRemove
@@ -458,6 +458,19 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
+ * Same as {@link AudioSystem#addDevicesRoleForCapturePreset(int, int, List)}
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param devices the list of devices to be added as role for the given capture preset
+ * @return {@link #SUCCESS} if successfully added
+ */
+ public int addDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ invalidateRoutingCache();
+ return AudioSystem.addDevicesRoleForCapturePreset(capturePreset, role, devices);
+ }
+
+ /**
* Same as {@link AudioSystem#}
* @param capturePreset
* @param role