4040import android .util .ArrayMap ;
4141import android .util .ArraySet ;
4242import android .util .Log ;
43+ import android .util .Pair ;
4344import android .util .Slog ;
4445
4546import com .android .internal .annotations .GuardedBy ;
4647import com .android .internal .annotations .VisibleForTesting ;
4748
4849import java .io .PrintWriter ;
4950import java .util .ArrayList ;
51+ import java .util .HashMap ;
5052import java .util .HashSet ;
53+ import java .util .Iterator ;
5154import java .util .LinkedHashMap ;
5255import java .util .List ;
5356import java .util .Objects ;
@@ -74,31 +77,58 @@ public class AudioDeviceInventory {
7477
7578 private final Object mDeviceInventoryLock = new Object ();
7679 @ GuardedBy ("mDeviceInventoryLock" )
77- private final ArrayList <AdiDeviceState > mDeviceInventory = new ArrayList <>(0 );
78-
80+ private final HashMap <Pair <Integer , String >, AdiDeviceState > mDeviceInventory = new HashMap <>();
7981
8082 List <AdiDeviceState > getImmutableDeviceInventory () {
8183 synchronized (mDeviceInventoryLock ) {
82- return List . copyOf (mDeviceInventory );
84+ return new ArrayList < AdiDeviceState > (mDeviceInventory . values () );
8385 }
8486 }
8587
8688 void addDeviceStateToInventory (AdiDeviceState deviceState ) {
8789 synchronized (mDeviceInventoryLock ) {
88- mDeviceInventory .add (deviceState );
90+ mDeviceInventory .put (deviceState .getDeviceId (), deviceState );
91+ }
92+ }
93+
94+ /**
95+ * Adds a new entry in mDeviceInventory if the AudioDeviceAttributes passed is an sink
96+ * Bluetooth device and no corresponding entry already exists.
97+ * @param ada the device to add if needed
98+ */
99+ void addAudioDeviceInInventoryIfNeeded (AudioDeviceAttributes ada ) {
100+ if (!AudioSystem .isBluetoothOutDevice (ada .getInternalType ())) {
101+ return ;
102+ }
103+ synchronized (mDeviceInventoryLock ) {
104+ if (findDeviceStateForAudioDeviceAttributes (ada , ada .getType ()) != null ) {
105+ return ;
106+ }
107+ AdiDeviceState ads = new AdiDeviceState (
108+ ada .getType (), ada .getInternalType (), ada .getAddress ());
109+ mDeviceInventory .put (ads .getDeviceId (), ads );
89110 }
111+ mDeviceBroker .persistAudioDeviceSettings ();
90112 }
91113
114+ /**
115+ * Finds the device state that matches the passed {@link AudioDeviceAttributes} and device
116+ * type. Note: currently this method only returns a valid device for A2DP and BLE devices.
117+ *
118+ * @param ada attributes of device to match
119+ * @param canonicalDeviceType external device type to match
120+ * @return the found {@link AdiDeviceState} matching a cached A2DP or BLE device or
121+ * {@code null} otherwise.
122+ */
92123 AdiDeviceState findDeviceStateForAudioDeviceAttributes (AudioDeviceAttributes ada ,
93124 int canonicalDeviceType ) {
94125 final boolean isWireless = isBluetoothDevice (ada .getInternalType ());
95-
96126 synchronized (mDeviceInventoryLock ) {
97- for (AdiDeviceState deviceSetting : mDeviceInventory ) {
98- if (deviceSetting .getDeviceType () == canonicalDeviceType
127+ for (AdiDeviceState deviceState : mDeviceInventory . values () ) {
128+ if (deviceState .getDeviceType () == canonicalDeviceType
99129 && (!isWireless || ada .getAddress ().equals (
100- deviceSetting .getDeviceAddress ()))) {
101- return deviceSetting ;
130+ deviceState .getDeviceAddress ()))) {
131+ return deviceState ;
102132 }
103133 }
104134 }
@@ -308,7 +338,7 @@ public String toString() {
308338 + " devices:" + devices ); });
309339 pw .println ("\n devices:\n " );
310340 synchronized (mDeviceInventoryLock ) {
311- for (AdiDeviceState device : mDeviceInventory ) {
341+ for (AdiDeviceState device : mDeviceInventory . values () ) {
312342 pw .println ("\t " + device + "\n " );
313343 }
314344 }
@@ -695,8 +725,8 @@ void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int str
695725 }
696726
697727 /*package*/ void registerStrategyPreferredDevicesDispatcher (
698- @ NonNull IStrategyPreferredDevicesDispatcher dispatcher ) {
699- mPrefDevDispatchers .register (dispatcher );
728+ @ NonNull IStrategyPreferredDevicesDispatcher dispatcher , boolean isPrivileged ) {
729+ mPrefDevDispatchers .register (dispatcher , isPrivileged );
700730 }
701731
702732 /*package*/ void unregisterStrategyPreferredDevicesDispatcher (
@@ -730,8 +760,8 @@ void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int str
730760 }
731761
732762 /*package*/ void registerCapturePresetDevicesRoleDispatcher (
733- @ NonNull ICapturePresetDevicesRoleDispatcher dispatcher ) {
734- mDevRoleCapturePresetDispatchers .register (dispatcher );
763+ @ NonNull ICapturePresetDevicesRoleDispatcher dispatcher , boolean isPrivileged ) {
764+ mDevRoleCapturePresetDispatchers .register (dispatcher , isPrivileged );
735765 }
736766
737767 /*package*/ void unregisterCapturePresetDevicesRoleDispatcher (
@@ -809,6 +839,9 @@ public boolean isDeviceConnected(@NonNull AudioDeviceAttributes device) {
809839 mConnectedDevices .put (deviceKey , new DeviceInfo (
810840 device , deviceName , address , AudioSystem .AUDIO_FORMAT_DEFAULT ));
811841 mDeviceBroker .postAccessoryPlugMediaUnmute (device );
842+ if (AudioSystem .isBluetoothScoDevice (device )) {
843+ addAudioDeviceInInventoryIfNeeded (attributes );
844+ }
812845 mmi .set (MediaMetrics .Property .STATE , MediaMetrics .Value .CONNECTED ).record ();
813846 return true ;
814847 } else if (!connect && isConnected ) {
@@ -1038,8 +1071,9 @@ private void makeA2dpDeviceAvailable(String address, String name, String eventSo
10381071 mDeviceBroker .setBluetoothA2dpOnInt (true , true /*fromA2dp*/ , eventSource );
10391072 // at this point there could be another A2DP device already connected in APM, but it
10401073 // doesn't matter as this new one will overwrite the previous one
1041- final int res = mAudioSystem .setDeviceConnectionState (new AudioDeviceAttributes (
1042- AudioSystem .DEVICE_OUT_BLUETOOTH_A2DP , address , name ),
1074+ AudioDeviceAttributes ada = new AudioDeviceAttributes (
1075+ AudioSystem .DEVICE_OUT_BLUETOOTH_A2DP , address , name );
1076+ final int res = mAudioSystem .setDeviceConnectionState (ada ,
10431077 AudioSystem .DEVICE_STATE_AVAILABLE , a2dpCodec );
10441078
10451079 // TODO: log in MediaMetrics once distinction between connection failure and
@@ -1061,8 +1095,7 @@ private void makeA2dpDeviceAvailable(String address, String name, String eventSo
10611095 // The convention for head tracking sensors associated with A2DP devices is to
10621096 // use a UUID derived from the MAC address as follows:
10631097 // time_low = 0, time_mid = 0, time_hi = 0, clock_seq = 0, node = MAC Address
1064- UUID sensorUuid = UuidUtils .uuidFromAudioDeviceAttributes (
1065- new AudioDeviceAttributes (AudioSystem .DEVICE_OUT_BLUETOOTH_A2DP , address ));
1098+ UUID sensorUuid = UuidUtils .uuidFromAudioDeviceAttributes (ada );
10661099 final DeviceInfo di = new DeviceInfo (AudioSystem .DEVICE_OUT_BLUETOOTH_A2DP , name ,
10671100 address , a2dpCodec , sensorUuid );
10681101 final String diKey = di .getKey ();
@@ -1073,8 +1106,10 @@ private void makeA2dpDeviceAvailable(String address, String name, String eventSo
10731106
10741107 mDeviceBroker .postAccessoryPlugMediaUnmute (AudioSystem .DEVICE_OUT_BLUETOOTH_A2DP );
10751108 setCurrentAudioRouteNameIfPossible (name , true /*fromA2dp*/ );
1109+ addAudioDeviceInInventoryIfNeeded (ada );
10761110 }
10771111
1112+
10781113 @ GuardedBy ("mDevicesLock" )
10791114 private void makeA2dpDeviceUnavailableNow (String address , int a2dpCodec ) {
10801115 MediaMetrics .Item mmi = new MediaMetrics .Item (mMetricsId + "a2dp." + address )
@@ -1168,9 +1203,9 @@ private void makeHearingAidDeviceAvailable(
11681203 final int hearingAidVolIndex = mDeviceBroker .getVssVolumeForDevice (streamType ,
11691204 AudioSystem .DEVICE_OUT_HEARING_AID );
11701205 mDeviceBroker .postSetHearingAidVolumeIndex (hearingAidVolIndex , streamType );
1171-
1172- mAudioSystem . setDeviceConnectionState ( new AudioDeviceAttributes (
1173- AudioSystem . DEVICE_OUT_HEARING_AID , address , name ) ,
1206+ AudioDeviceAttributes ada = new AudioDeviceAttributes (
1207+ AudioSystem . DEVICE_OUT_HEARING_AID , address , name );
1208+ mAudioSystem . setDeviceConnectionState ( ada ,
11741209 AudioSystem .DEVICE_STATE_AVAILABLE ,
11751210 AudioSystem .AUDIO_FORMAT_DEFAULT );
11761211 mConnectedDevices .put (
@@ -1181,6 +1216,7 @@ private void makeHearingAidDeviceAvailable(
11811216 mDeviceBroker .postApplyVolumeOnDevice (streamType ,
11821217 AudioSystem .DEVICE_OUT_HEARING_AID , "makeHearingAidDeviceAvailable" );
11831218 setCurrentAudioRouteNameIfPossible (name , false /*fromA2dp*/ );
1219+ addAudioDeviceInInventoryIfNeeded (ada );
11841220 new MediaMetrics .Item (mMetricsId + "makeHearingAidDeviceAvailable" )
11851221 .set (MediaMetrics .Property .ADDRESS , address != null ? address : "" )
11861222 .set (MediaMetrics .Property .DEVICE ,
@@ -1217,13 +1253,15 @@ private void makeLeAudioDeviceAvailable(String address, String name, int streamT
12171253 */
12181254 mDeviceBroker .setBluetoothA2dpOnInt (true , false /*fromA2dp*/ , eventSource );
12191255
1220- AudioSystem .setDeviceConnectionState (new AudioDeviceAttributes (device , address , name ),
1256+ AudioDeviceAttributes ada = new AudioDeviceAttributes (device , address , name );
1257+ AudioSystem .setDeviceConnectionState (ada ,
12211258 AudioSystem .DEVICE_STATE_AVAILABLE ,
12221259 AudioSystem .AUDIO_FORMAT_DEFAULT );
12231260 mConnectedDevices .put (DeviceInfo .makeDeviceListKey (device , address ),
12241261 new DeviceInfo (device , name , address , AudioSystem .AUDIO_FORMAT_DEFAULT ));
12251262 mDeviceBroker .postAccessoryPlugMediaUnmute (device );
12261263 setCurrentAudioRouteNameIfPossible (name , /*fromA2dp=*/ false );
1264+ addAudioDeviceInInventoryIfNeeded (ada );
12271265 }
12281266
12291267 if (streamType == AudioSystem .STREAM_DEFAULT ) {
@@ -1524,6 +1562,9 @@ private void dispatchPreferredDevice(int strategy,
15241562 final int nbDispatchers = mPrefDevDispatchers .beginBroadcast ();
15251563 for (int i = 0 ; i < nbDispatchers ; i ++) {
15261564 try {
1565+ if (!((Boolean ) mPrefDevDispatchers .getBroadcastCookie (i ))) {
1566+ devices = mDeviceBroker .anonymizeAudioDeviceAttributesListUnchecked (devices );
1567+ }
15271568 mPrefDevDispatchers .getBroadcastItem (i ).dispatchPrefDevicesChanged (
15281569 strategy , devices );
15291570 } catch (RemoteException e ) {
@@ -1537,6 +1578,9 @@ private void dispatchDevicesRoleForCapturePreset(
15371578 final int nbDispatchers = mDevRoleCapturePresetDispatchers .beginBroadcast ();
15381579 for (int i = 0 ; i < nbDispatchers ; ++i ) {
15391580 try {
1581+ if (!((Boolean ) mDevRoleCapturePresetDispatchers .getBroadcastCookie (i ))) {
1582+ devices = mDeviceBroker .anonymizeAudioDeviceAttributesListUnchecked (devices );
1583+ }
15401584 mDevRoleCapturePresetDispatchers .getBroadcastItem (i ).dispatchDevicesRoleChanged (
15411585 capturePreset , role , devices );
15421586 } catch (RemoteException e ) {
@@ -1561,19 +1605,20 @@ UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
15611605 int deviceCatalogSize = 0 ;
15621606 synchronized (mDeviceInventoryLock ) {
15631607 deviceCatalogSize = mDeviceInventory .size ();
1564- }
1565- final StringBuilder settingsBuilder = new StringBuilder (
1608+
1609+ final StringBuilder settingsBuilder = new StringBuilder (
15661610 deviceCatalogSize * AdiDeviceState .getPeristedMaxSize ());
15671611
1568- synchronized (mDeviceInventoryLock ) {
1569- for (int i = 0 ; i < mDeviceInventory .size (); i ++) {
1570- settingsBuilder .append (mDeviceInventory .get (i ).toPersistableString ());
1571- if (i != mDeviceInventory .size () - 1 ) {
1572- settingsBuilder .append (SETTING_DEVICE_SEPARATOR_CHAR );
1573- }
1612+ Iterator <AdiDeviceState > iterator = mDeviceInventory .values ().iterator ();
1613+ if (iterator .hasNext ()) {
1614+ settingsBuilder .append (iterator .next ().toPersistableString ());
1615+ }
1616+ while (iterator .hasNext ()) {
1617+ settingsBuilder .append (SETTING_DEVICE_SEPARATOR_CHAR );
1618+ settingsBuilder .append (iterator .next ().toPersistableString ());
15741619 }
1620+ return settingsBuilder .toString ();
15751621 }
1576- return settingsBuilder .toString ();
15771622 }
15781623
15791624 /*package*/ void setDeviceSettings (String settings ) {
0 commit comments