[Audiosharing] Listen to onProfileConnectionStateChanged
of LE_AUDIO_BROADCAST_ASSISTANT to be more precise on device connection status upon bluetooth on/off. Also increase test coverage.
Test: atest -c com.android.settings.connecteddevice.audiosharing.audiostreams Flag: com.android.settingslib.flags.enable_le_audio_qr_code_private_broadcast_sharing Bug: 345686602 Change-Id: Ia78b1fe19bff3cb179794db1dc09374db13818d8
This commit is contained in:
@@ -16,24 +16,22 @@
|
|||||||
|
|
||||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.bluetooth.Utils;
|
import com.android.settings.bluetooth.Utils;
|
||||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback {
|
public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback {
|
||||||
private static final String TAG = "AudioStreamsActiveDeviceSummaryUpdater";
|
|
||||||
private static final boolean DEBUG = BluetoothUtils.D;
|
|
||||||
private final LocalBluetoothManager mBluetoothManager;
|
private final LocalBluetoothManager mBluetoothManager;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
@Nullable private String mSummary;
|
@Nullable private String mSummary;
|
||||||
@@ -47,17 +45,20 @@ public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActiveDeviceChanged(
|
public void onBluetoothStateChanged(@AdapterState int bluetoothState) {
|
||||||
@Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
if (bluetoothState == BluetoothAdapter.STATE_OFF) {
|
||||||
if (DEBUG) {
|
notifyChangeIfNeeded();
|
||||||
Log.d(
|
|
||||||
TAG,
|
|
||||||
"onActiveDeviceChanged() with activeDevice : "
|
|
||||||
+ (activeDevice == null ? "null" : activeDevice.getAddress())
|
|
||||||
+ " on profile : "
|
|
||||||
+ bluetoothProfile);
|
|
||||||
}
|
}
|
||||||
if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProfileConnectionStateChanged(
|
||||||
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
|
@ConnectionState int state,
|
||||||
|
int bluetoothProfile) {
|
||||||
|
if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
|
||||||
|
&& (state == BluetoothAdapter.STATE_CONNECTED
|
||||||
|
|| state == BluetoothAdapter.STATE_DISCONNECTED)) {
|
||||||
notifyChangeIfNeeded();
|
notifyChangeIfNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
|
||||||
import com.android.settings.bluetooth.Utils;
|
import com.android.settings.bluetooth.Utils;
|
||||||
@@ -44,9 +44,13 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo
|
|||||||
private final BluetoothCallback mBluetoothCallback =
|
private final BluetoothCallback mBluetoothCallback =
|
||||||
new BluetoothCallback() {
|
new BluetoothCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onActiveDeviceChanged(
|
public void onProfileConnectionStateChanged(
|
||||||
@Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
|
@ConnectionState int state,
|
||||||
|
int bluetoothProfile) {
|
||||||
|
if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
|
||||||
|
&& (state == BluetoothAdapter.STATE_CONNECTED
|
||||||
|
|| state == BluetoothAdapter.STATE_DISCONNECTED)) {
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
|||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
|
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
|
||||||
private static final String TAG = "AudioStreamsProgressCategoryCallback";
|
private static final String TAG = "AudioStreamsProgressCategoryCallback";
|
||||||
@@ -53,10 +52,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
|
|||||||
@Override
|
@Override
|
||||||
public void onSearchStarted(int reason) {
|
public void onSearchStarted(int reason) {
|
||||||
super.onSearchStarted(reason);
|
super.onSearchStarted(reason);
|
||||||
if (mCategoryController == null) {
|
|
||||||
Log.w(TAG, "onSearchStarted() : mCategoryController is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCategoryController.setScanning(true);
|
mCategoryController.setScanning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,10 +64,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
|
|||||||
@Override
|
@Override
|
||||||
public void onSearchStopped(int reason) {
|
public void onSearchStopped(int reason) {
|
||||||
super.onSearchStopped(reason);
|
super.onSearchStopped(reason);
|
||||||
if (mCategoryController == null) {
|
|
||||||
Log.w(TAG, "onSearchStopped() : mCategoryController is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCategoryController.setScanning(false);
|
mCategoryController.setScanning(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,10 +77,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
|
|||||||
@Override
|
@Override
|
||||||
public void onSourceFound(BluetoothLeBroadcastMetadata source) {
|
public void onSourceFound(BluetoothLeBroadcastMetadata source) {
|
||||||
super.onSourceFound(source);
|
super.onSourceFound(source);
|
||||||
if (mCategoryController == null) {
|
|
||||||
Log.w(TAG, "onSourceFound() : mCategoryController is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCategoryController.handleSourceFound(source);
|
mCategoryController.handleSourceFound(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -47,9 +48,13 @@ public class AudioStreamsScanQrCodeController extends BasePreferenceController
|
|||||||
final BluetoothCallback mBluetoothCallback =
|
final BluetoothCallback mBluetoothCallback =
|
||||||
new BluetoothCallback() {
|
new BluetoothCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onActiveDeviceChanged(
|
public void onProfileConnectionStateChanged(
|
||||||
@Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
|
@ConnectionState int state,
|
||||||
|
int bluetoothProfile) {
|
||||||
|
if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
|
||||||
|
&& (state == BluetoothAdapter.STATE_CONNECTED
|
||||||
|
|| state == BluetoothAdapter.STATE_DISCONNECTED)) {
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class AudioStreamStateHandlerTest {
|
||||||
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
|
private static final int SUMMARY_RES = 1;
|
||||||
|
private static final String SUMMARY = "summary";
|
||||||
|
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
|
@Mock private AudioStreamsProgressCategoryController mController;
|
||||||
|
@Mock private AudioStreamsHelper mHelper;
|
||||||
|
@Mock private AudioStreamPreference mPreference;
|
||||||
|
private AudioStreamStateHandler mHandler;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mHandler = spy(new AudioStreamStateHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleStateChange_noChange_doNothing() {
|
||||||
|
when(mHandler.getStateEnum())
|
||||||
|
.thenReturn(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState
|
||||||
|
.ADD_SOURCE_BAD_CODE);
|
||||||
|
when(mPreference.getAudioStreamState())
|
||||||
|
.thenReturn(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState
|
||||||
|
.ADD_SOURCE_BAD_CODE);
|
||||||
|
|
||||||
|
mHandler.handleStateChange(mPreference, mController, mHelper);
|
||||||
|
|
||||||
|
verify(mPreference, never()).setAudioStreamState(any());
|
||||||
|
verify(mHandler, never()).performAction(any(), any(), any());
|
||||||
|
verify(mPreference, never()).setIsConnected(anyBoolean(), anyString(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleStateChange_setNewState() {
|
||||||
|
when(mHandler.getStateEnum())
|
||||||
|
.thenReturn(AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED);
|
||||||
|
when(mPreference.getAudioStreamState())
|
||||||
|
.thenReturn(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState
|
||||||
|
.ADD_SOURCE_BAD_CODE);
|
||||||
|
|
||||||
|
mHandler.handleStateChange(mPreference, mController, mHelper);
|
||||||
|
|
||||||
|
verify(mPreference)
|
||||||
|
.setAudioStreamState(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED);
|
||||||
|
verify(mHandler).performAction(any(), any(), any());
|
||||||
|
verify(mPreference).setIsConnected(eq(true), eq(""), eq(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleStateChange_setNewState_newSummary_newListener() {
|
||||||
|
Preference.OnPreferenceClickListener listener =
|
||||||
|
mock(Preference.OnPreferenceClickListener.class);
|
||||||
|
when(mHandler.getStateEnum())
|
||||||
|
.thenReturn(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState
|
||||||
|
.ADD_SOURCE_BAD_CODE);
|
||||||
|
when(mHandler.getSummary()).thenReturn(SUMMARY_RES);
|
||||||
|
when(mHandler.getOnClickListener(any())).thenReturn(listener);
|
||||||
|
when(mPreference.getAudioStreamState())
|
||||||
|
.thenReturn(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_FAILED);
|
||||||
|
when(mPreference.getContext()).thenReturn(mContext);
|
||||||
|
doReturn(SUMMARY).when(mContext).getString(anyInt());
|
||||||
|
|
||||||
|
mHandler.handleStateChange(mPreference, mController, mHelper);
|
||||||
|
|
||||||
|
verify(mPreference)
|
||||||
|
.setAudioStreamState(
|
||||||
|
AudioStreamsProgressCategoryController.AudioStreamState
|
||||||
|
.ADD_SOURCE_BAD_CODE);
|
||||||
|
verify(mHandler).performAction(any(), any(), any());
|
||||||
|
verify(mPreference).setIsConnected(eq(false), eq(SUMMARY), eq(listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSummary() {
|
||||||
|
int res = mHandler.getSummary();
|
||||||
|
assertThat(res).isEqualTo(AudioStreamStateHandler.EMPTY_STRING_RES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetOnClickListener() {
|
||||||
|
Preference.OnPreferenceClickListener listener = mHandler.getOnClickListener(mController);
|
||||||
|
assertThat(listener).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetStateEnum() {
|
||||||
|
var state = mHandler.getStateEnum();
|
||||||
|
assertThat(state)
|
||||||
|
.isEqualTo(AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN);
|
||||||
|
}
|
||||||
|
}
|
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -76,25 +77,46 @@ public class AudioStreamsActiveDeviceSummaryUpdaterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onActiveDeviceChanged_notLeProfile_doNothing() {
|
public void unregister_doNothing() {
|
||||||
mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, 0);
|
mUpdater.register(false);
|
||||||
|
|
||||||
assertThat(mUpdatedSummary).isNull();
|
assertThat(mUpdatedSummary).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onActiveDeviceChanged_leProfile_summaryUpdated() {
|
public void onProfileConnectionStateChanged_notLeAssistProfile_doNothing() {
|
||||||
|
mUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 0, 0);
|
||||||
|
|
||||||
|
assertThat(mUpdatedSummary).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onProfileConnectionStateChanged_leAssistantProfile_summaryUpdated() {
|
||||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||||
mCachedBluetoothDevice);
|
mCachedBluetoothDevice);
|
||||||
when(mCachedBluetoothDevice.getName()).thenReturn(DEVICE_NAME);
|
when(mCachedBluetoothDevice.getName()).thenReturn(DEVICE_NAME);
|
||||||
mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, BluetoothProfile.LE_AUDIO);
|
mUpdater.onProfileConnectionStateChanged(
|
||||||
|
mCachedBluetoothDevice,
|
||||||
|
BluetoothAdapter.STATE_CONNECTED,
|
||||||
|
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||||
|
|
||||||
assertThat(mUpdatedSummary).isEqualTo(DEVICE_NAME);
|
assertThat(mUpdatedSummary).isEqualTo(DEVICE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onActiveDeviceChanged_leProfile_noDevice_summaryUpdated() {
|
public void onActiveDeviceChanged_leAssistantProfile_noDevice_summaryUpdated() {
|
||||||
mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, BluetoothProfile.LE_AUDIO);
|
mUpdater.onProfileConnectionStateChanged(
|
||||||
|
mCachedBluetoothDevice,
|
||||||
|
BluetoothAdapter.STATE_CONNECTED,
|
||||||
|
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||||
|
|
||||||
|
assertThat(mUpdatedSummary)
|
||||||
|
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onBluetoothStateOff_summaryUpdated() {
|
||||||
|
mUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||||
|
|
||||||
assertThat(mUpdatedSummary)
|
assertThat(mUpdatedSummary)
|
||||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
|
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
|
||||||
|
@@ -23,11 +23,13 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
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 static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.bluetooth.BluetoothStatusCodes;
|
import android.bluetooth.BluetoothStatusCodes;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -42,6 +44,7 @@ import com.android.settings.bluetooth.Utils;
|
|||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||||
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||||
@@ -57,6 +60,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
@@ -116,7 +120,7 @@ public class AudioStreamsCategoryControllerTest {
|
|||||||
when(mBroadcast.isProfileReady()).thenReturn(true);
|
when(mBroadcast.isProfileReady()).thenReturn(true);
|
||||||
when(mAssistant.isProfileReady()).thenReturn(true);
|
when(mAssistant.isProfileReady()).thenReturn(true);
|
||||||
when(mVolumeControl.isProfileReady()).thenReturn(true);
|
when(mVolumeControl.isProfileReady()).thenReturn(true);
|
||||||
mController = new AudioStreamsCategoryController(mContext, KEY);
|
mController = spy(new AudioStreamsCategoryController(mContext, KEY));
|
||||||
mPreference = new Preference(mContext);
|
mPreference = new Preference(mContext);
|
||||||
when(mScreen.findPreference(KEY)).thenReturn(mPreference);
|
when(mScreen.findPreference(KEY)).thenReturn(mPreference);
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
@@ -228,4 +232,21 @@ public class AudioStreamsCategoryControllerTest {
|
|||||||
shadowOf(Looper.getMainLooper()).idle();
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
assertThat(mPreference.isVisible()).isTrue();
|
assertThat(mPreference.isVisible()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onProfileConnectionStateChanged_updateVisibility() {
|
||||||
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||||
|
ArgumentCaptor<BluetoothCallback> argumentCaptor =
|
||||||
|
ArgumentCaptor.forClass(BluetoothCallback.class);
|
||||||
|
mController.onStart(mLifecycleOwner);
|
||||||
|
verify(mBluetoothEventManager).registerCallback(argumentCaptor.capture());
|
||||||
|
|
||||||
|
BluetoothCallback callback = argumentCaptor.getValue();
|
||||||
|
callback.onProfileConnectionStateChanged(
|
||||||
|
mCachedBluetoothDevice,
|
||||||
|
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT,
|
||||||
|
BluetoothAdapter.STATE_DISCONNECTED);
|
||||||
|
|
||||||
|
verify(mController).updateVisibility();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowAlertDialog;
|
||||||
|
import org.robolectric.shadows.ShadowLooper;
|
||||||
|
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(
|
||||||
|
shadows = {
|
||||||
|
ShadowAlertDialog.class,
|
||||||
|
})
|
||||||
|
public class AudioStreamsDialogFragmentTest {
|
||||||
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
private AudioStreamsDialogFragment.DialogBuilder mDialogBuilder;
|
||||||
|
private AudioStreamsDialogFragment mFragment;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mDialogBuilder = spy(new AudioStreamsDialogFragment.DialogBuilder(mContext));
|
||||||
|
mFragment = new AudioStreamsDialogFragment(mDialogBuilder, SettingsEnums.PAGE_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowAlertDialog.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMetricsCategory() {
|
||||||
|
int dialogId = mFragment.getMetricsCategory();
|
||||||
|
|
||||||
|
assertThat(dialogId).isEqualTo(SettingsEnums.PAGE_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnCreateDialog() {
|
||||||
|
mFragment.onCreateDialog(Bundle.EMPTY);
|
||||||
|
|
||||||
|
verify(mDialogBuilder).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShowDialog() {
|
||||||
|
FragmentController.setupFragment(mFragment);
|
||||||
|
AudioStreamsDialogFragment.show(mFragment, mDialogBuilder, SettingsEnums.PAGE_UNKNOWN);
|
||||||
|
ShadowLooper.idleMainLooper();
|
||||||
|
|
||||||
|
var dialog = ShadowAlertDialog.getLatestAlertDialog();
|
||||||
|
assertThat(dialog).isNotNull();
|
||||||
|
assertThat(dialog.isShowing()).isTrue();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||||
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class AudioStreamsProgressCategoryCallbackTest {
|
||||||
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
|
@Mock private AudioStreamsProgressCategoryController mController;
|
||||||
|
@Mock private BluetoothDevice mDevice;
|
||||||
|
@Mock private BluetoothLeBroadcastReceiveState mState;
|
||||||
|
@Mock private BluetoothLeBroadcastMetadata mMetadata;
|
||||||
|
private AudioStreamsProgressCategoryCallback mCallback;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mCallback = new AudioStreamsProgressCategoryCallback(mController);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnReceiveStateChanged_connected() {
|
||||||
|
List<Long> bisSyncState = new ArrayList<>();
|
||||||
|
bisSyncState.add(1L);
|
||||||
|
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||||
|
mCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 0, mState);
|
||||||
|
|
||||||
|
verify(mController).handleSourceConnected(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnReceiveStateChanged_badCode() {
|
||||||
|
when(mState.getPaSyncState())
|
||||||
|
.thenReturn(BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED);
|
||||||
|
when(mState.getBigEncryptionState())
|
||||||
|
.thenReturn(BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_BAD_CODE);
|
||||||
|
mCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 0, mState);
|
||||||
|
|
||||||
|
verify(mController).handleSourceConnectBadCode(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSearchStartFailed() {
|
||||||
|
mCallback.onSearchStartFailed(/* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).showToast(anyString());
|
||||||
|
verify(mController).setScanning(anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSearchStarted() {
|
||||||
|
mCallback.onSearchStarted(/* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).setScanning(anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSearchStopFailed() {
|
||||||
|
mCallback.onSearchStopFailed(/* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).showToast(anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSearchStopped() {
|
||||||
|
mCallback.onSearchStopped(/* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).setScanning(anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSourceAddFailed() {
|
||||||
|
when(mMetadata.getBroadcastId()).thenReturn(1);
|
||||||
|
mCallback.onSourceAddFailed(mDevice, mMetadata, /* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).handleSourceFailedToConnect(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSourceFound() {
|
||||||
|
mCallback.onSourceFound(mMetadata);
|
||||||
|
|
||||||
|
verify(mController).handleSourceFound(mMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSourceLost() {
|
||||||
|
mCallback.onSourceLost(/* broadcastId= */ 1);
|
||||||
|
|
||||||
|
verify(mController).handleSourceLost(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSourceRemoveFailed() {
|
||||||
|
mCallback.onSourceRemoveFailed(mDevice, /* sourceId= */ 0, /* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).showToast(anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSourceRemoved() {
|
||||||
|
mCallback.onSourceRemoved(mDevice, /* sourceId= */ 0, /* reason= */ 0);
|
||||||
|
|
||||||
|
verify(mController).handleSourceRemoved();
|
||||||
|
}
|
||||||
|
}
|
@@ -16,29 +16,38 @@
|
|||||||
|
|
||||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
|
import static android.app.settings.SettingsEnums.AUDIO_STREAM_MAIN;
|
||||||
|
|
||||||
|
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsScanQrCodeController.REQUEST_SCAN_BT_BROADCAST_QR_CODE;
|
||||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||||
|
|
||||||
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.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
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.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@@ -46,6 +55,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
@@ -139,17 +149,46 @@ public class AudioStreamsScanQrCodeControllerTest {
|
|||||||
public void onPreferenceClick_hasFragment_launchSubSetting() {
|
public void onPreferenceClick_hasFragment_launchSubSetting() {
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
mController.setFragment(mFragment);
|
mController.setFragment(mFragment);
|
||||||
|
when(mFragment.getMetricsCategory()).thenReturn(AUDIO_STREAM_MAIN);
|
||||||
|
|
||||||
var listener = mPreference.getOnPreferenceClickListener();
|
var listener = mPreference.getOnPreferenceClickListener();
|
||||||
assertThat(listener).isNotNull();
|
assertThat(listener).isNotNull();
|
||||||
|
|
||||||
|
// mContext is not an Activity context, calling startActivity() from outside of an Activity
|
||||||
|
// context requires the FLAG_ACTIVITY_NEW_TASK flag, create a mock to avoid this
|
||||||
|
// AndroidRuntimeException.
|
||||||
|
Context activityContext = mock(Context.class);
|
||||||
|
when(mPreference.getContext()).thenReturn(activityContext);
|
||||||
|
when(mPreference.getKey()).thenReturn(AudioStreamsScanQrCodeController.KEY);
|
||||||
|
|
||||||
var clicked = listener.onPreferenceClick(mPreference);
|
var clicked = listener.onPreferenceClick(mPreference);
|
||||||
|
|
||||||
|
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||||
|
ArgumentCaptor<Integer> requestCodeCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||||
|
verify(mFragment)
|
||||||
|
.startActivityForResult(intentCaptor.capture(), requestCodeCaptor.capture());
|
||||||
|
|
||||||
|
Intent intent = intentCaptor.getValue();
|
||||||
|
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||||
|
.isEqualTo(AudioStreamsQrCodeScanFragment.class.getName());
|
||||||
|
assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
|
||||||
|
.isEqualTo(R.string.audio_streams_main_page_scan_qr_code_title);
|
||||||
|
assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0))
|
||||||
|
.isEqualTo(AUDIO_STREAM_MAIN);
|
||||||
|
|
||||||
|
int requestCode = requestCodeCaptor.getValue();
|
||||||
|
assertThat(requestCode).isEqualTo(REQUEST_SCAN_BT_BROADCAST_QR_CODE);
|
||||||
|
|
||||||
assertThat(clicked).isTrue();
|
assertThat(clicked).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateVisibility_noConnected_invisible() {
|
public void updateVisibility_noConnected_invisible() {
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
mController.mBluetoothCallback.onActiveDeviceChanged(mDevice, BluetoothProfile.LE_AUDIO);
|
mController.mBluetoothCallback.onProfileConnectionStateChanged(
|
||||||
|
mDevice,
|
||||||
|
BluetoothAdapter.STATE_DISCONNECTED,
|
||||||
|
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||||
|
|
||||||
assertThat(mPreference.isVisible()).isFalse();
|
assertThat(mPreference.isVisible()).isFalse();
|
||||||
}
|
}
|
||||||
@@ -158,7 +197,10 @@ public class AudioStreamsScanQrCodeControllerTest {
|
|||||||
public void updateVisibility_hasConnected_visible() {
|
public void updateVisibility_hasConnected_visible() {
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
|
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
|
||||||
mController.mBluetoothCallback.onActiveDeviceChanged(mDevice, BluetoothProfile.LE_AUDIO);
|
mController.mBluetoothCallback.onProfileConnectionStateChanged(
|
||||||
|
mDevice,
|
||||||
|
BluetoothAdapter.STATE_CONNECTED,
|
||||||
|
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||||
|
|
||||||
assertThat(mPreference.isVisible()).isTrue();
|
assertThat(mPreference.isVisible()).isTrue();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user