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

Commit 6642b87b authored by Haijie Hong's avatar Haijie Hong Committed by Android (Google) Code Review
Browse files

Merge "Update preferred transport when HID and LeAudio profile are connected" into main

parents f15aa9f9 644b0b83
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -52,3 +52,13 @@ flag {
  description: "Hide exclusively managed Bluetooth devices in BT settings menu."
  bug: "324475542"
}

flag {
    name: "enable_set_preferred_transport_for_le_audio_device"
    namespace: "bluetooth"
    description: "Enable setting preferred transport for Le Audio device"
    bug: "330581926"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+28 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.settingslib.bluetooth;

import static com.android.settingslib.flags.Flags.enableSetPreferredTransportForLeAudioDevice;

import android.annotation.CallbackExecutor;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
@@ -288,6 +290,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                        mLocalNapRoleConnected = true;
                    }
                }
                if (enableSetPreferredTransportForLeAudioDevice()
                        && profile instanceof HidProfile) {
                    updatePreferredTransport();
                }
            } else if (profile instanceof MapProfile
                    && newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
                profile.setEnabled(mDevice, false);
@@ -300,12 +306,34 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                mLocalNapRoleConnected = false;
            }

            if (enableSetPreferredTransportForLeAudioDevice()
                    && profile instanceof LeAudioProfile) {
                updatePreferredTransport();
            }

            HearingAidStatsLogUtils.updateHistoryIfNeeded(mContext, this, profile, newProfileState);
        }

        fetchActiveDevices();
    }

    private void updatePreferredTransport() {
        if (mProfiles.stream().noneMatch(p -> p instanceof LeAudioProfile)
                || mProfiles.stream().noneMatch(p -> p instanceof HidProfile)) {
            return;
        }
        // Both LeAudioProfile and HidProfile are connectable.
        if (!mProfileManager
                .getHidProfile()
                .setPreferredTransport(
                        mDevice,
                        mProfileManager.getLeAudioProfile().isEnabled(mDevice)
                                ? BluetoothDevice.TRANSPORT_LE
                                : BluetoothDevice.TRANSPORT_BREDR)) {
            Log.w(TAG, "Fail to set preferred transport");
        }
    }

    @VisibleForTesting
    void setProfileConnectedStatus(int profileId, boolean isFailed) {
        switch (profileId) {
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;

import com.android.settingslib.R;

import java.util.List;
@@ -187,6 +189,14 @@ public class HidProfile implements LocalBluetoothProfile {
        }
    }

    /** Set preferred transport for the device */
    public boolean setPreferredTransport(@NonNull BluetoothDevice device, int transport) {
        if (mService != null) {
            mService.setPreferredTransport(device, transport);
        }
        return false;
    }

    protected void finalize() {
        Log.d(TAG, "finalize()");
        if (mService != null) {
+1 −2
Original line number Diff line number Diff line
@@ -572,8 +572,7 @@ public class LocalBluetoothProfileManager {
        return mSapProfile;
    }

    @VisibleForTesting
    HidProfile getHidProfile() {
    public HidProfile getHidProfile() {
        return mHidProfile;
    }

+34 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.settingslib.bluetooth;

import static com.android.settingslib.flags.Flags.FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
@@ -86,6 +88,9 @@ public class CachedBluetoothDeviceTest {
    private HapClientProfile mHapClientProfile;
    @Mock
    private LeAudioProfile mLeAudioProfile;

    @Mock
    private HidProfile mHidProfile;
    @Mock
    private BluetoothDevice mDevice;
    @Mock
@@ -104,6 +109,7 @@ public class CachedBluetoothDeviceTest {
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TV_MEDIA_OUTPUT_DIALOG);
        mSetFlagsRule.enableFlags(FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE);
        mContext = RuntimeEnvironment.application;
        mAudioManager = mContext.getSystemService(AudioManager.class);
        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
@@ -118,6 +124,8 @@ public class CachedBluetoothDeviceTest {
        when(mHearingAidProfile.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID);
        when(mLeAudioProfile.isProfileReady()).thenReturn(true);
        when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
        when(mHidProfile.isProfileReady()).thenReturn(true);
        when(mHidProfile.getProfileId()).thenReturn(BluetoothProfile.HID_HOST);
        mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
        mSubCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mSubDevice));
        doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
@@ -1819,6 +1827,32 @@ public class CachedBluetoothDeviceTest {
        assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
    }

    @Test
    public void leAudioHidDevice_leAudioEnabled_setPreferredTransportToLE() {

        when(mProfileManager.getHidProfile()).thenReturn(mHidProfile);
        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(true);

        updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED);
        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);

        verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_LE);
    }

    @Test
    public void leAudioHidDevice_leAudioDisabled_setPreferredTransportToBredr() {
        when(mProfileManager.getHidProfile()).thenReturn(mHidProfile);
        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(false);

        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_DISCONNECTED);
        updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED);

        verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_BREDR);
    }

    private HearingAidInfo getLeftAshaHearingAidInfo() {
        return new HearingAidInfo.Builder()
                .setAshaDeviceSide(HearingAidProfile.DeviceSide.SIDE_LEFT)