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

Commit 72fa7e6d authored by Yiyi Shen's avatar Yiyi Shen Committed by Android (Google) Code Review
Browse files

Merge "[Cleanup] Clean up flag disable_audio_sharing_auto_pick_fallback_in_ui" into main

parents 112ccd7a f3b57c0d
Loading
Loading
Loading
Loading
+0 −12
Original line number Original line Diff line number Diff line
@@ -235,18 +235,6 @@ public class BluetoothEventManager {


        LocalBluetoothLeBroadcast broadcast = mBtManager == null ? null
        LocalBluetoothLeBroadcast broadcast = mBtManager == null ? null
                : mBtManager.getProfileManager().getLeAudioBroadcastProfile();
                : mBtManager.getProfileManager().getLeAudioBroadcastProfile();
        LocalBluetoothLeBroadcastAssistant assistant = mBtManager == null ? null
                : mBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
        // Trigger updateFallbackActiveDeviceIfNeeded when ASSISTANT profile disconnected when
        // audio sharing is enabled.
        if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
                && state == BluetoothAdapter.STATE_DISCONNECTED
                && BluetoothUtils.isAudioSharingUIAvailable(mContext)
                && broadcast != null && assistant != null && broadcast.isProfileReady()
                && assistant.isProfileReady()) {
            Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, ASSISTANT profile disconnected");
            broadcast.updateFallbackActiveDeviceIfNeeded();
        }
        // Dispatch handleOnProfileStateChanged to local broadcast profile
        // Dispatch handleOnProfileStateChanged to local broadcast profile
        if (Flags.promoteAudioSharingForSecondAutoConnectedLeaDevice()
        if (Flags.promoteAudioSharingForSecondAutoConnectedLeaDevice()
                && broadcast != null
                && broadcast != null
+0 −110
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.settingslib.bluetooth;


import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;


import static com.android.settingslib.Utils.isAudioModeOngoingCall;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED_BY_RECEIVER;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED_BY_RECEIVER;
@@ -74,17 +73,14 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;


/**
/**
 * LocalBluetoothLeBroadcast provides an interface between the Settings app and the functionality of
 * LocalBluetoothLeBroadcast provides an interface between the Settings app and the functionality of
@@ -334,7 +330,6 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
                                        + ", sourceId = "
                                        + ", sourceId = "
                                        + sourceId);
                                        + sourceId);
                    }
                    }
                    updateFallbackActiveDeviceIfNeeded();
                }
                }


                @Override
                @Override
@@ -1205,111 +1200,6 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
        }
        }
    }
    }


    /** Update fallback active device if needed. */
    public void updateFallbackActiveDeviceIfNeeded() {
        if (Flags.disableAudioSharingAutoPickFallbackInUi() || (mContext != null
                && Flags.audioSharingDeveloperOption()
                && BluetoothUtils.getAudioSharingPreviewValue(mContext.getContentResolver()))) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, disable flag is on");
            return;
        }
        if (mIsWorkProfile) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded for work profile.");
            return;
        }
        if (isAudioModeOngoingCall(mContext)) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to ongoing call");
            return;
        }
        Map<Integer, List<BluetoothDevice>> deviceGroupsInBroadcast = getDeviceGroupsInBroadcast();
        if (deviceGroupsInBroadcast.isEmpty()) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no sinks in broadcast");
            return;
        }
        int targetGroupId = BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
        int fallbackActiveGroupId = BluetoothUtils.getPrimaryGroupIdForBroadcast(
                mContext.getContentResolver());
        if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)) {
            int userPreferredPrimaryGroupId = getUserPreferredPrimaryGroupId();
            if (userPreferredPrimaryGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
                    && deviceGroupsInBroadcast.containsKey(userPreferredPrimaryGroupId)) {
                if (userPreferredPrimaryGroupId == fallbackActiveGroupId) {
                    Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, already user preferred");
                    return;
                } else {
                    targetGroupId = userPreferredPrimaryGroupId;
                }
            }
            if (targetGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
                // If there is no user preferred primary device, set the earliest connected
                // device in sharing session as the fallback.
                targetGroupId = getEarliestConnectedDeviceGroup(deviceGroupsInBroadcast);
            }
        } else {
            // Set the earliest connected device in sharing session as the fallback.
            targetGroupId = getEarliestConnectedDeviceGroup(deviceGroupsInBroadcast);
        }
        Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, target group id = " + targetGroupId);
        if (targetGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return;
        if (targetGroupId == fallbackActiveGroupId) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, already is fallback");
            return;
        }
        CachedBluetoothDevice targetCachedDevice = getMainDevice(
                deviceGroupsInBroadcast.get(targetGroupId));
        if (targetCachedDevice == null) {
            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, fail to find main device");
            return;
        }
        Log.d(
                TAG,
                "updateFallbackActiveDeviceIfNeeded, set active device: "
                        + targetCachedDevice.getDevice());
        targetCachedDevice.setActive();
    }

    @NonNull
    private Map<Integer, List<BluetoothDevice>> getDeviceGroupsInBroadcast() {
        if (mServiceBroadcastAssistant == null) return new HashMap<>();
        boolean hysteresisModeFixEnabled =
                BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext);
        List<BluetoothDevice> connectedDevices = mServiceBroadcastAssistant.getConnectedDevices();
        return connectedDevices.stream()
                .filter(
                        device -> {
                            List<BluetoothLeBroadcastReceiveState> sourceList =
                                    mServiceBroadcastAssistant.getAllSources(device);
                            return !sourceList.isEmpty() && sourceList.stream().anyMatch(
                                    source -> hysteresisModeFixEnabled
                                            ? BluetoothUtils.isSourceMatched(source, mBroadcastId)
                                            : BluetoothUtils.isConnected(source));
                        })
                .collect(Collectors.groupingBy(
                        device -> BluetoothUtils.getGroupId(mDeviceManager.findDevice(device))));
    }

    private int getEarliestConnectedDeviceGroup(
            @NonNull Map<Integer, List<BluetoothDevice>> deviceGroups) {
        List<BluetoothDevice> devices =
                BluetoothAdapter.getDefaultAdapter().getMostRecentlyConnectedDevices();
        // Find the earliest connected device in sharing session.
        int targetDeviceIdx = -1;
        int targetGroupId = BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
        for (Map.Entry<Integer, List<BluetoothDevice>> entry : deviceGroups.entrySet()) {
            for (BluetoothDevice device : entry.getValue()) {
                if (devices.contains(device)) {
                    int idx = devices.indexOf(device);
                    if (idx > targetDeviceIdx) {
                        targetDeviceIdx = idx;
                        targetGroupId = entry.getKey();
                    }
                }
            }
        }
        Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, earliest group id = " + targetGroupId);
        return targetGroupId;
    }

    @Nullable
    @Nullable
    private CachedBluetoothDevice getMainDevice(@Nullable List<BluetoothDevice> devices) {
    private CachedBluetoothDevice getMainDevice(@Nullable List<BluetoothDevice> devices) {
        if (devices == null || devices.isEmpty()) return null;
        if (devices == null || devices.isEmpty()) return null;
+4 −67
Original line number Original line Diff line number Diff line
@@ -221,8 +221,7 @@ public class BluetoothEventManagerTest {


    /**
    /**
     * dispatchProfileConnectionStateChanged should not call {@link
     * dispatchProfileConnectionStateChanged should not call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded and
     * LocalBluetoothLeBroadcast}#handleProfileConnected when audio sharing flag is off.
     * {@link LocalBluetoothLeBroadcast}#handleProfileConnected when audio sharing flag is off.
     */
     */
    @Test
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
@@ -234,15 +233,13 @@ public class BluetoothEventManagerTest {
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);


        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
    }
    }


    /**
    /**
     * dispatchProfileConnectionStateChanged should not call {@link
     * dispatchProfileConnectionStateChanged should not call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded and
     * LocalBluetoothLeBroadcast}#handleProfileConnected when the device does not support audio
     * {@link LocalBluetoothLeBroadcast}#handleProfileConnected when the device does not support
     * sharing.
     * audio sharing.
     */
     */
    @Test
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
@@ -254,50 +251,12 @@ public class BluetoothEventManagerTest {
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);


        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
    }
    }


    /**
    /**
     * dispatchProfileConnectionStateChanged should not call {@link
     * dispatchProfileConnectionStateChanged should not call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing profile is
     * LocalBluetoothLeBroadcast}#handleProfileConnected when triggered for work profile.
     * not ready.
     */
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    public void dispatchProfileConnectionStateChanged_profileNotReady_noUpdateFallbackDevice() {
        setUpAudioSharing(/* enableFlag= */ true, /* enableFeature= */ true, /* enableProfile= */
                false, /* workProfile= */ false);
        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
                mCachedBluetoothDevice,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);

        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
    }

    /**
     * dispatchProfileConnectionStateChanged should not call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when triggered for profile
     * other than LE_AUDIO_BROADCAST_ASSISTANT or state other than STATE_DISCONNECTED.
     */
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    public void dispatchProfileConnectionStateChanged_notAssistantProfile_noUpdateFallbackDevice() {
        setUpAudioSharing(/* enableFlag= */ true, /* enableFeature= */ true, /* enableProfile= */
                true, /* workProfile= */ false);
        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
                mCachedBluetoothDevice,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO);

        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
    }

    /**
     * dispatchProfileConnectionStateChanged should not call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded and
     * {@link LocalBluetoothLeBroadcast}#handleProfileConnected when triggered for work profile.
     */
     */
    @Test
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
@@ -309,26 +268,6 @@ public class BluetoothEventManagerTest {
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);


        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
    }

    /**
     * dispatchProfileConnectionStateChanged should call {@link
     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when assistant profile is
     * disconnected and audio sharing is enabled.
     */
    @Test
    @EnableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE)
    public void dispatchProfileConnectionStateChanged_assistDisconnected_updateFallbackDevice() {
        setUpAudioSharing(/* enableFlag= */ true, /* enableFeature= */ true, /* enableProfile= */
                true, /* workProfile= */ false);
        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
                mCachedBluetoothDevice,
                BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);

        verify(mBroadcast).updateFallbackActiveDeviceIfNeeded();
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
        verify(mBroadcast, never()).handleProfileConnected(any(), anyInt(), any());
    }
    }


@@ -347,14 +286,12 @@ public class BluetoothEventManagerTest {
                BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);


        verify(mBroadcast, never()).updateFallbackActiveDeviceIfNeeded();
        verify(mBroadcast).handleProfileConnected(mCachedBluetoothDevice,
        verify(mBroadcast).handleProfileConnected(mCachedBluetoothDevice,
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mBtManager);
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mBtManager);
    }
    }


    private void setUpAudioSharing(boolean enableFlag, boolean enableFeature,
    private void setUpAudioSharing(boolean enableFlag, boolean enableFeature,
            boolean enableProfile, boolean workProfile) {
            boolean enableProfile, boolean workProfile) {
        mSetFlagsRule.disableFlags(Flags.FLAG_DISABLE_AUDIO_SHARING_AUTO_PICK_FALLBACK_IN_UI);
        if (enableFlag) {
        if (enableFlag) {
            mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
            mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
        } else {
        } else {