Merge "Move enable/disable LE Audio to Utils" into main
This commit is contained in:
@@ -419,32 +419,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
|||||||
mContext,
|
mContext,
|
||||||
SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_OFF,
|
SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_OFF,
|
||||||
isCurrentDeviceInOrByPassAllowList());
|
isCurrentDeviceInOrByPassAllowList());
|
||||||
|
Utils.setLeAudioEnabled(mManager, List.copyOf(mCachedDeviceGroup), false);
|
||||||
LocalBluetoothProfile asha = mProfileManager.getHearingAidProfile();
|
|
||||||
LocalBluetoothProfile broadcastAssistant =
|
|
||||||
mProfileManager.getLeAudioBroadcastAssistantProfile();
|
|
||||||
|
|
||||||
for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
|
|
||||||
Log.d(TAG,
|
|
||||||
"device:" + leAudioDevice.getDevice().getAnonymizedAddress()
|
|
||||||
+ " disable LE profile");
|
|
||||||
profile.setEnabled(leAudioDevice.getDevice(), false);
|
|
||||||
if (asha != null) {
|
|
||||||
asha.setEnabled(leAudioDevice.getDevice(), true);
|
|
||||||
}
|
|
||||||
if (broadcastAssistant != null) {
|
|
||||||
Log.d(TAG,
|
|
||||||
"device:" + leAudioDevice.getDevice().getAnonymizedAddress()
|
|
||||||
+ " disable LE broadcast assistant profile");
|
|
||||||
broadcastAssistant.setEnabled(leAudioDevice.getDevice(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false)) {
|
|
||||||
Log.i(TAG, "Enabling classic audio profiles because dual mode is disabled");
|
|
||||||
enableProfileAfterUserDisablesLeAudio(mProfileManager.getA2dpProfile());
|
|
||||||
enableProfileAfterUserDisablesLeAudio(mProfileManager.getHeadsetProfile());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -462,75 +437,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
|||||||
mContext,
|
mContext,
|
||||||
SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_ON,
|
SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_ON,
|
||||||
isCurrentDeviceInOrByPassAllowList());
|
isCurrentDeviceInOrByPassAllowList());
|
||||||
|
Utils.setLeAudioEnabled(mManager, List.copyOf(mCachedDeviceGroup), true);
|
||||||
if (!SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false)) {
|
|
||||||
Log.i(TAG, "Disabling classic audio profiles because dual mode is disabled");
|
|
||||||
disableProfileBeforeUserEnablesLeAudio(mProfileManager.getA2dpProfile());
|
|
||||||
disableProfileBeforeUserEnablesLeAudio(mProfileManager.getHeadsetProfile());
|
|
||||||
}
|
|
||||||
LocalBluetoothProfile asha = mProfileManager.getHearingAidProfile();
|
|
||||||
LocalBluetoothProfile broadcastAssistant =
|
|
||||||
mProfileManager.getLeAudioBroadcastAssistantProfile();
|
|
||||||
|
|
||||||
for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
|
|
||||||
Log.d(TAG,
|
|
||||||
"device:" + leAudioDevice.getDevice().getAnonymizedAddress()
|
|
||||||
+ " enable LE profile");
|
|
||||||
profile.setEnabled(leAudioDevice.getDevice(), true);
|
|
||||||
if (asha != null) {
|
|
||||||
asha.setEnabled(leAudioDevice.getDevice(), false);
|
|
||||||
}
|
|
||||||
if (broadcastAssistant != null) {
|
|
||||||
Log.d(TAG,
|
|
||||||
"device:" + leAudioDevice.getDevice().getAnonymizedAddress()
|
|
||||||
+ " enable LE broadcast assistant profile");
|
|
||||||
broadcastAssistant.setEnabled(leAudioDevice.getDevice(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableProfileBeforeUserEnablesLeAudio(LocalBluetoothProfile profile) {
|
|
||||||
if (profile != null && mProfileDeviceMap.get(profile.toString()) != null) {
|
|
||||||
Log.d(TAG, "Disable " + profile.toString() + " before user enables LE");
|
|
||||||
for (CachedBluetoothDevice profileDevice : mProfileDeviceMap.get(profile.toString())) {
|
|
||||||
if (profile.isEnabled(profileDevice.getDevice())) {
|
|
||||||
Log.d(TAG, "The " + profileDevice.getDevice().getAnonymizedAddress() + ":"
|
|
||||||
+ profile.toString() + " set disable");
|
|
||||||
profile.setEnabled(profileDevice.getDevice(), false);
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "The " + profileDevice.getDevice().getAnonymizedAddress() + ":"
|
|
||||||
+ profile.toString() + " profile is disabled. Do nothing.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (profile == null) {
|
|
||||||
Log.w(TAG, "profile is null");
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, profile.toString() + " is not in " + mProfileDeviceMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableProfileAfterUserDisablesLeAudio(LocalBluetoothProfile profile) {
|
|
||||||
if (profile != null && mProfileDeviceMap.get(profile.toString()) != null) {
|
|
||||||
Log.d(TAG, "enable " + profile.toString() + "after user disables LE");
|
|
||||||
for (CachedBluetoothDevice profileDevice : mProfileDeviceMap.get(profile.toString())) {
|
|
||||||
if (!profile.isEnabled(profileDevice.getDevice())) {
|
|
||||||
Log.d(TAG, "The " + profileDevice.getDevice().getAnonymizedAddress() + ":"
|
|
||||||
+ profile.toString() + " set enable");
|
|
||||||
profile.setEnabled(profileDevice.getDevice(), true);
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "The " + profileDevice.getDevice().getAnonymizedAddress() + ":"
|
|
||||||
+ profile.toString() + " profile is enabled. Do nothing.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (profile == null) {
|
|
||||||
Log.w(TAG, "profile is null");
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, profile.toString() + " is not in " + mProfileDeviceMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -28,6 +28,7 @@ import android.content.pm.ActivityInfo;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -45,15 +46,20 @@ import com.android.settingslib.bluetooth.BluetoothUtils;
|
|||||||
import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener;
|
import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
|
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||||
|
import com.android.settingslib.bluetooth.LeAudioProfile;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -70,6 +76,7 @@ import java.util.stream.Collectors;
|
|||||||
public final class Utils {
|
public final class Utils {
|
||||||
|
|
||||||
private static final String TAG = "BluetoothUtils";
|
private static final String TAG = "BluetoothUtils";
|
||||||
|
private static final String ENABLE_DUAL_MODE_AUDIO = "persist.bluetooth.enable_dual_mode_audio";
|
||||||
|
|
||||||
static final boolean V = BluetoothUtils.V; // verbose logging
|
static final boolean V = BluetoothUtils.V; // verbose logging
|
||||||
static final boolean D = BluetoothUtils.D; // regular logging
|
static final boolean D = BluetoothUtils.D; // regular logging
|
||||||
@@ -360,4 +367,119 @@ public final class Utils {
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Enables/disables LE Audio profile for the device. */
|
||||||
|
public static void setLeAudioEnabled(
|
||||||
|
@NonNull LocalBluetoothManager manager,
|
||||||
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
|
boolean enable) {
|
||||||
|
List<CachedBluetoothDevice> devices =
|
||||||
|
List.copyOf(findAllCachedBluetoothDevicesByGroupId(manager, cachedDevice));
|
||||||
|
setLeAudioEnabled(manager, devices, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enables/disables LE Audio profile for the devices in the same csip group. */
|
||||||
|
public static void setLeAudioEnabled(
|
||||||
|
@NonNull LocalBluetoothManager manager,
|
||||||
|
@NonNull List<CachedBluetoothDevice> devicesWithSameGroupId,
|
||||||
|
boolean enable) {
|
||||||
|
LocalBluetoothProfileManager profileManager = manager.getProfileManager();
|
||||||
|
LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile();
|
||||||
|
List<CachedBluetoothDevice> leAudioDevices =
|
||||||
|
getDevicesWithProfile(devicesWithSameGroupId, leAudioProfile);
|
||||||
|
if (leAudioDevices.isEmpty()) {
|
||||||
|
Log.i(TAG, "Fail to setLeAudioEnabled, no LE Audio profile found.");
|
||||||
|
}
|
||||||
|
boolean dualModeEnabled = SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false);
|
||||||
|
|
||||||
|
if (enable && !dualModeEnabled) {
|
||||||
|
Log.i(TAG, "Disabling classic audio profiles because dual mode is disabled");
|
||||||
|
setProfileEnabledWhenChangingLeAudio(
|
||||||
|
devicesWithSameGroupId, profileManager.getA2dpProfile(), false);
|
||||||
|
setProfileEnabledWhenChangingLeAudio(
|
||||||
|
devicesWithSameGroupId, profileManager.getHeadsetProfile(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
HearingAidProfile asha = profileManager.getHearingAidProfile();
|
||||||
|
LocalBluetoothLeBroadcastAssistant broadcastAssistant =
|
||||||
|
profileManager.getLeAudioBroadcastAssistantProfile();
|
||||||
|
|
||||||
|
for (CachedBluetoothDevice leAudioDevice : leAudioDevices) {
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"device:"
|
||||||
|
+ leAudioDevice.getDevice().getAnonymizedAddress()
|
||||||
|
+ " set LE profile enabled: "
|
||||||
|
+ enable);
|
||||||
|
leAudioProfile.setEnabled(leAudioDevice.getDevice(), enable);
|
||||||
|
if (asha != null) {
|
||||||
|
asha.setEnabled(leAudioDevice.getDevice(), !enable);
|
||||||
|
}
|
||||||
|
if (broadcastAssistant != null) {
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"device:"
|
||||||
|
+ leAudioDevice.getDevice().getAnonymizedAddress()
|
||||||
|
+ " enable LE broadcast assistant profile: "
|
||||||
|
+ enable);
|
||||||
|
broadcastAssistant.setEnabled(leAudioDevice.getDevice(), enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enable && !dualModeEnabled) {
|
||||||
|
Log.i(TAG, "Enabling classic audio profiles because dual mode is disabled");
|
||||||
|
setProfileEnabledWhenChangingLeAudio(
|
||||||
|
devicesWithSameGroupId, profileManager.getA2dpProfile(), true);
|
||||||
|
setProfileEnabledWhenChangingLeAudio(
|
||||||
|
devicesWithSameGroupId, profileManager.getHeadsetProfile(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<CachedBluetoothDevice> getDevicesWithProfile(
|
||||||
|
List<CachedBluetoothDevice> devices, LocalBluetoothProfile profile) {
|
||||||
|
List<CachedBluetoothDevice> devicesWithProfile = new ArrayList<>();
|
||||||
|
for (CachedBluetoothDevice device : devices) {
|
||||||
|
for (LocalBluetoothProfile currentProfile : device.getProfiles()) {
|
||||||
|
if (currentProfile.toString().equals(profile.toString())) {
|
||||||
|
devicesWithProfile.add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devicesWithProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setProfileEnabledWhenChangingLeAudio(
|
||||||
|
List<CachedBluetoothDevice> devices,
|
||||||
|
@Nullable LocalBluetoothProfile profile,
|
||||||
|
boolean enable) {
|
||||||
|
if (profile == null) {
|
||||||
|
Log.i(TAG, "profile is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<CachedBluetoothDevice> deviceWithProfile = getDevicesWithProfile(devices, profile);
|
||||||
|
Log.d(TAG, "Set " + profile + " enabled:" + enable + " when switching LE Audio");
|
||||||
|
for (CachedBluetoothDevice profileDevice : deviceWithProfile) {
|
||||||
|
if (profile.isEnabled(profileDevice.getDevice()) != enable) {
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"The "
|
||||||
|
+ profileDevice.getDevice().getAnonymizedAddress()
|
||||||
|
+ ":"
|
||||||
|
+ profile
|
||||||
|
+ " set to "
|
||||||
|
+ enable);
|
||||||
|
profile.setEnabled(profileDevice.getDevice(), enable);
|
||||||
|
} else {
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"The "
|
||||||
|
+ profileDevice.getDevice().getAnonymizedAddress()
|
||||||
|
+ ":"
|
||||||
|
+ profile
|
||||||
|
+ " profile is already "
|
||||||
|
+ enable
|
||||||
|
+ ". Do nothing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,22 +18,29 @@ package com.android.settings.bluetooth;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothCsipSetCoordinator;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
import com.android.settingslib.bluetooth.A2dpProfile;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
|
import com.android.settingslib.bluetooth.HeadsetProfile;
|
||||||
|
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||||
|
import com.android.settingslib.bluetooth.LeAudioProfile;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
@@ -41,8 +48,8 @@ import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
|||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -52,10 +59,8 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
|
||||||
public class UtilsTest {
|
public class UtilsTest {
|
||||||
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
|
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
|
||||||
private static final String TEMP_BOND_METADATA =
|
private static final String TEMP_BOND_METADATA =
|
||||||
@@ -73,6 +78,14 @@ public class UtilsTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private LocalBluetoothLeBroadcastAssistant mAssistant;
|
private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||||
@Mock
|
@Mock
|
||||||
|
private A2dpProfile mA2dpProfile;
|
||||||
|
@Mock
|
||||||
|
private HeadsetProfile mHeadsetProfile;
|
||||||
|
@Mock
|
||||||
|
private LeAudioProfile mLeAudioProfile;
|
||||||
|
@Mock
|
||||||
|
private HearingAidProfile mHearingAidProfile;
|
||||||
|
@Mock
|
||||||
private CachedBluetoothDeviceManager mDeviceManager;
|
private CachedBluetoothDeviceManager mDeviceManager;
|
||||||
|
|
||||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||||
@@ -80,17 +93,14 @@ public class UtilsTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mMetricsFeatureProvider = FakeFeatureFactory.setupForTest().getMetricsFeatureProvider();
|
mMetricsFeatureProvider = FakeFeatureFactory.setupForTest().getMetricsFeatureProvider();
|
||||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
|
|
||||||
mLocalBtManager = Utils.getLocalBtManager(mContext);
|
|
||||||
when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager);
|
when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager);
|
||||||
when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||||
when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||||
when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
||||||
}
|
when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
|
||||||
|
when(mProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
|
||||||
@After
|
when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
|
||||||
public void tearDown() {
|
when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
|
||||||
ShadowBluetoothUtils.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -170,4 +180,148 @@ public class UtilsTest {
|
|||||||
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state));
|
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state));
|
||||||
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue();
|
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void enableLeAudioProfile_multipleDeviceInGroup() {
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
|
||||||
|
CachedBluetoothDevice cachedDevice3 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
BluetoothDevice device2 = mock(BluetoothDevice.class);
|
||||||
|
BluetoothDevice device3 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice2.getDevice()).thenReturn(device2);
|
||||||
|
when(cachedDevice3.getDevice()).thenReturn(device3);
|
||||||
|
when(cachedDevice1.getMemberDevice()).thenReturn(ImmutableSet.of(cachedDevice2));
|
||||||
|
when(mDeviceManager.getCachedDevicesCopy())
|
||||||
|
.thenReturn(ImmutableList.of(cachedDevice1, cachedDevice3));
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(1);
|
||||||
|
when(cachedDevice2.getGroupId()).thenReturn(1);
|
||||||
|
when(cachedDevice3.getGroupId()).thenReturn(2);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(cachedDevice2.getProfiles()).thenReturn(ImmutableList.of(mLeAudioProfile));
|
||||||
|
when(cachedDevice3.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice2, true);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, true);
|
||||||
|
verify(mLeAudioProfile).setEnabled(device2, true);
|
||||||
|
verify(mHearingAidProfile).setEnabled(device1, false);
|
||||||
|
verify(mAssistant).setEnabled(device1, true);
|
||||||
|
verify(mLeAudioProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
verify(mA2dpProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
verify(mHeadsetProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void enableLeAudioProfile_dualModeEnabled_a2dpAndHfpNotChanged() {
|
||||||
|
SystemProperties.set("persist.bluetooth.enable_dual_mode_audio", "true");
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(mA2dpProfile.isEnabled(device1)).thenReturn(true);
|
||||||
|
when(mHeadsetProfile.isEnabled(device1)).thenReturn(true);
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice1, true);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, true);
|
||||||
|
verify(mA2dpProfile, never()).setEnabled(device1, false);
|
||||||
|
verify(mHeadsetProfile, never()).setEnabled(device1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void enableLeAudioProfile_dualModeDisabled_disableA2dpAndHfp() {
|
||||||
|
SystemProperties.set("persist.bluetooth.enable_dual_mode_audio", "false");
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(mA2dpProfile.isEnabled(device1)).thenReturn(true);
|
||||||
|
when(mHeadsetProfile.isEnabled(device1)).thenReturn(true);
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice1, true);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, true);
|
||||||
|
verify(mA2dpProfile).setEnabled(device1, false);
|
||||||
|
verify(mHeadsetProfile).setEnabled(device1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void disableLeAudioProfile_multipleDeviceInGroup() {
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
|
||||||
|
CachedBluetoothDevice cachedDevice3 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
BluetoothDevice device2 = mock(BluetoothDevice.class);
|
||||||
|
BluetoothDevice device3 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice2.getDevice()).thenReturn(device2);
|
||||||
|
when(cachedDevice3.getDevice()).thenReturn(device3);
|
||||||
|
when(cachedDevice1.getMemberDevice()).thenReturn(ImmutableSet.of(cachedDevice2));
|
||||||
|
when(mDeviceManager.getCachedDevicesCopy())
|
||||||
|
.thenReturn(ImmutableList.of(cachedDevice1, cachedDevice3));
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(1);
|
||||||
|
when(cachedDevice2.getGroupId()).thenReturn(1);
|
||||||
|
when(cachedDevice3.getGroupId()).thenReturn(2);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(cachedDevice2.getProfiles()).thenReturn(ImmutableList.of(mLeAudioProfile));
|
||||||
|
when(cachedDevice3.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice2, false);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, false);
|
||||||
|
verify(mLeAudioProfile).setEnabled(device2, false);
|
||||||
|
verify(mHearingAidProfile).setEnabled(device1, true);
|
||||||
|
verify(mAssistant).setEnabled(device1, false);
|
||||||
|
verify(mLeAudioProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
verify(mA2dpProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
verify(mHeadsetProfile, never()).setEnabled(eq(device3), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void disableLeAudioProfile_dualModeEnabled_a2dpAndHfpNotChanged() {
|
||||||
|
SystemProperties.set("persist.bluetooth.enable_dual_mode_audio", "true");
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(mA2dpProfile.isEnabled(device1)).thenReturn(false);
|
||||||
|
when(mHeadsetProfile.isEnabled(device1)).thenReturn(false);
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice1, false);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, false);
|
||||||
|
verify(mA2dpProfile, never()).setEnabled(device1, true);
|
||||||
|
verify(mHeadsetProfile, never()).setEnabled(device1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void disableLeAudioProfile_dualModeDisabled_enableA2dpAndHfp() {
|
||||||
|
SystemProperties.set("persist.bluetooth.enable_dual_mode_audio", "false");
|
||||||
|
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||||
|
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||||
|
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||||
|
when(cachedDevice1.getGroupId()).thenReturn(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||||
|
when(cachedDevice1.getProfiles())
|
||||||
|
.thenReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile, mLeAudioProfile));
|
||||||
|
when(mA2dpProfile.isEnabled(device1)).thenReturn(false);
|
||||||
|
when(mHeadsetProfile.isEnabled(device1)).thenReturn(false);
|
||||||
|
|
||||||
|
Utils.setLeAudioEnabled(mLocalBtManager, cachedDevice1, false);
|
||||||
|
|
||||||
|
verify(mLeAudioProfile).setEnabled(device1, false);
|
||||||
|
verify(mA2dpProfile).setEnabled(device1, true);
|
||||||
|
verify(mHeadsetProfile).setEnabled(device1, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,24 +18,48 @@ package com.android.settings.testutils.shadow;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.settings.bluetooth.Utils;
|
import com.android.settings.bluetooth.Utils;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
|
||||||
import org.robolectric.annotation.Implementation;
|
import org.robolectric.annotation.Implementation;
|
||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
import org.robolectric.annotation.Resetter;
|
import org.robolectric.annotation.Resetter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/** Robolectric shadow for the bluetooth utils. */
|
/** Robolectric shadow for the bluetooth utils. */
|
||||||
@Implements(Utils.class)
|
@Implements(Utils.class)
|
||||||
public class ShadowBluetoothUtils {
|
public class ShadowBluetoothUtils {
|
||||||
|
|
||||||
public static LocalBluetoothManager sLocalBluetoothManager;
|
public static LocalBluetoothManager sLocalBluetoothManager;
|
||||||
|
private static final Map<CachedBluetoothDevice, Boolean> sLeAudioState = new HashMap<>();
|
||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
protected static LocalBluetoothManager getLocalBtManager(Context context) {
|
protected static LocalBluetoothManager getLocalBtManager(Context context) {
|
||||||
return sLocalBluetoothManager;
|
return sLocalBluetoothManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets le audio state for the device. */
|
||||||
|
@Implementation
|
||||||
|
public static void setLeAudioEnabled(
|
||||||
|
@NonNull LocalBluetoothManager manager,
|
||||||
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
|
boolean enable) {
|
||||||
|
sLeAudioState.put(cachedDevice, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks whether le audio is enabled for the device. */
|
||||||
|
public static boolean isLeAudioEnabled(@NonNull CachedBluetoothDevice cachedDevice) {
|
||||||
|
if (sLeAudioState.containsKey(cachedDevice)) {
|
||||||
|
return sLeAudioState.get(cachedDevice);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Resets the local bluetooth manager to null. */
|
/** Resets the local bluetooth manager to null. */
|
||||||
@Resetter
|
@Resetter
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
|
Reference in New Issue
Block a user