Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ea119ee authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

Merge "AudioDeviceInventory: add cache for preferred device roles" into udc-dev am: 6a9342d7

parents 4185a2f4 6a9342d7
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -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);
+301 −35
Original line number Diff line number Diff line
@@ -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,33 +835,70 @@ 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);
        }
        return status;
    }

        if (status == AudioSystem.SUCCESS) {
            mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
    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);
    }
        return status;

    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(
@@ -849,6 +911,207 @@ 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();
                }
            }
        }
    }

//-----------------------------------------------------------------------

    /**
@@ -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")