Merge changes I6322ccbb,Idc96c23d into main
* changes: [Audiosharing] Add tests. [Audiosharing] Add logging 3.
This commit is contained in:
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* 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.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsDashboardFragment.KEY_BROADCAST_METADATA;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import org.junit.After;
|
||||
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 org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowBluetoothAdapter.class,
|
||||
ShadowBluetoothUtils.class,
|
||||
})
|
||||
public class AudioStreamConfirmDialogTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
private static final String VALID_METADATA =
|
||||
"BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
|
||||
+ "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
|
||||
private static final String DEVICE_NAME = "device_name";
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
|
||||
@Mock private LocalBluetoothLeBroadcast mBroadcast;
|
||||
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock private VolumeControlProfile mVolumeControl;
|
||||
@Mock private BluetoothDevice mBluetoothDevice;
|
||||
private AudioStreamConfirmDialog mDialogFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter =
|
||||
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile())
|
||||
.thenReturn(mAssistant);
|
||||
when(mLocalBluetoothProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
|
||||
when(mBroadcast.isProfileReady()).thenReturn(true);
|
||||
when(mAssistant.isProfileReady()).thenReturn(true);
|
||||
when(mVolumeControl.isProfileReady()).thenReturn(true);
|
||||
|
||||
mDialogFragment = new AudioStreamConfirmDialog();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowBluetoothUtils.reset();
|
||||
mDialogFragment.dismiss();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showDialog_unsupported() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
FragmentController.setupFragment(
|
||||
mDialogFragment,
|
||||
FragmentActivity.class,
|
||||
/* containerViewId= */ 0,
|
||||
/* bundle= */ null);
|
||||
shadowMainLooper().idle();
|
||||
|
||||
assertThat(mDialogFragment.getMetricsCategory())
|
||||
.isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_FEATURE_UNSUPPORTED);
|
||||
|
||||
var dialog = mDialogFragment.getDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
TextView title = dialog.findViewById(R.id.dialog_title);
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
|
||||
TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
|
||||
assertThat(subtitle1).isNotNull();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
|
||||
assertThat(subtitle2).isNotNull();
|
||||
assertThat(subtitle2.getText())
|
||||
.isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.audio_streams_dialog_unsupported_device_subtitle));
|
||||
View leftButton = dialog.findViewById(R.id.left_button);
|
||||
assertThat(leftButton).isNotNull();
|
||||
assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(leftButton.hasOnClickListeners()).isFalse();
|
||||
View rightButton = dialog.findViewById(R.id.right_button);
|
||||
assertThat(rightButton).isNotNull();
|
||||
assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(rightButton.hasOnClickListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showDialog_noLeDevice() {
|
||||
FragmentController.setupFragment(
|
||||
mDialogFragment,
|
||||
FragmentActivity.class,
|
||||
/* containerViewId= */ 0,
|
||||
/* bundle= */ null);
|
||||
shadowMainLooper().idle();
|
||||
|
||||
assertThat(mDialogFragment.getMetricsCategory())
|
||||
.isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_NO_LE_DEVICE);
|
||||
|
||||
var dialog = mDialogFragment.getDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
|
||||
TextView title = dialog.findViewById(R.id.dialog_title);
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
|
||||
TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
|
||||
assertThat(subtitle1).isNotNull();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
|
||||
assertThat(subtitle2).isNotNull();
|
||||
assertThat(subtitle2.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_subtitle));
|
||||
View leftButton = dialog.findViewById(R.id.left_button);
|
||||
assertThat(leftButton).isNotNull();
|
||||
assertThat(leftButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
Button rightButton = dialog.findViewById(R.id.right_button);
|
||||
assertThat(rightButton).isNotNull();
|
||||
assertThat(rightButton.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_button));
|
||||
assertThat(rightButton.hasOnClickListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showDialog_noMetadata() {
|
||||
List<BluetoothDevice> devices = new ArrayList<>();
|
||||
devices.add(mBluetoothDevice);
|
||||
when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
|
||||
when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);
|
||||
|
||||
FragmentController.setupFragment(
|
||||
mDialogFragment,
|
||||
FragmentActivity.class,
|
||||
/* containerViewId= */ 0,
|
||||
/* bundle= */ null);
|
||||
shadowMainLooper().idle();
|
||||
|
||||
assertThat(mDialogFragment.getMetricsCategory())
|
||||
.isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_DATA_ERROR);
|
||||
|
||||
var dialog = mDialogFragment.getDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
TextView title = dialog.findViewById(R.id.dialog_title);
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
|
||||
TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
|
||||
assertThat(subtitle1).isNotNull();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
|
||||
assertThat(subtitle2).isNotNull();
|
||||
assertThat(subtitle2.getText())
|
||||
.isEqualTo(
|
||||
mContext.getString(R.string.audio_streams_dialog_cannot_play, DEVICE_NAME));
|
||||
View leftButton = dialog.findViewById(R.id.left_button);
|
||||
assertThat(leftButton).isNotNull();
|
||||
assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(leftButton.hasOnClickListeners()).isFalse();
|
||||
View rightButton = dialog.findViewById(R.id.right_button);
|
||||
assertThat(rightButton).isNotNull();
|
||||
assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(rightButton.hasOnClickListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showDialog_invalidMetadata() {
|
||||
List<BluetoothDevice> devices = new ArrayList<>();
|
||||
devices.add(mBluetoothDevice);
|
||||
when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
|
||||
when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(KEY_BROADCAST_METADATA, "invalid");
|
||||
FragmentController.of(mDialogFragment, intent)
|
||||
.create(/* containerViewId= */ 0, /* bundle= */ null)
|
||||
.start()
|
||||
.resume()
|
||||
.visible()
|
||||
.get();
|
||||
shadowMainLooper().idle();
|
||||
|
||||
assertThat(mDialogFragment.getMetricsCategory())
|
||||
.isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_DATA_ERROR);
|
||||
|
||||
var dialog = mDialogFragment.getDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
TextView title = dialog.findViewById(R.id.dialog_title);
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
|
||||
TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
|
||||
assertThat(subtitle1).isNotNull();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
|
||||
assertThat(subtitle2).isNotNull();
|
||||
assertThat(subtitle2.getText())
|
||||
.isEqualTo(
|
||||
mContext.getString(R.string.audio_streams_dialog_cannot_play, DEVICE_NAME));
|
||||
View leftButton = dialog.findViewById(R.id.left_button);
|
||||
assertThat(leftButton).isNotNull();
|
||||
assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(leftButton.hasOnClickListeners()).isFalse();
|
||||
View rightButton = dialog.findViewById(R.id.right_button);
|
||||
assertThat(rightButton).isNotNull();
|
||||
assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(rightButton.hasOnClickListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showDialog_confirmListen() {
|
||||
List<BluetoothDevice> devices = new ArrayList<>();
|
||||
devices.add(mBluetoothDevice);
|
||||
when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
|
||||
when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(KEY_BROADCAST_METADATA, VALID_METADATA);
|
||||
FragmentController.of(mDialogFragment, intent)
|
||||
.create(/* containerViewId= */ 0, /* bundle= */ null)
|
||||
.start()
|
||||
.resume()
|
||||
.visible()
|
||||
.get();
|
||||
shadowMainLooper().idle();
|
||||
|
||||
assertThat(mDialogFragment.getMetricsCategory())
|
||||
.isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_LISTEN);
|
||||
|
||||
var dialog = mDialogFragment.getDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
TextView title = dialog.findViewById(R.id.dialog_title);
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.getText())
|
||||
.isEqualTo(
|
||||
mContext.getString(R.string.audio_streams_dialog_listen_to_audio_stream));
|
||||
TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
|
||||
assertThat(subtitle1).isNotNull();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
|
||||
assertThat(subtitle2).isNotNull();
|
||||
assertThat(subtitle2.getText())
|
||||
.isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.audio_streams_dialog_control_volume, DEVICE_NAME));
|
||||
View leftButton = dialog.findViewById(R.id.left_button);
|
||||
assertThat(leftButton).isNotNull();
|
||||
assertThat(leftButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
Button rightButton = dialog.findViewById(R.id.right_button);
|
||||
assertThat(rightButton).isNotNull();
|
||||
assertThat(rightButton.getText())
|
||||
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_listen));
|
||||
assertThat(rightButton.hasOnClickListeners()).isTrue();
|
||||
}
|
||||
}
|
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_ID;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.DEVICES;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
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.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.media.session.ISession;
|
||||
import android.media.session.ISessionController;
|
||||
import android.media.session.MediaSessionManager;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowBluetoothAdapter.class,
|
||||
ShadowBluetoothUtils.class,
|
||||
ShadowAudioStreamsHelper.class,
|
||||
})
|
||||
public class AudioStreamMediaServiceTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
@Mock private Resources mResources;
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
|
||||
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
||||
@Mock private NotificationManager mNotificationManager;
|
||||
@Mock private MediaSessionManager mMediaSessionManager;
|
||||
@Mock private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
|
||||
@Mock private VolumeControlProfile mVolumeControlProfile;
|
||||
@Mock private BluetoothDevice mDevice;
|
||||
@Mock private ISession mISession;
|
||||
@Mock private ISessionController mISessionController;
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private DisplayMetrics mDisplayMetrics;
|
||||
@Mock private Context mContext;
|
||||
private AudioStreamMediaService mAudioStreamMediaService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter =
|
||||
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
|
||||
when(mLocalBtManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||
when(mLocalBluetoothProfileManager.getVolumeControlProfile())
|
||||
.thenReturn(mVolumeControlProfile);
|
||||
|
||||
mAudioStreamMediaService = spy(new AudioStreamMediaService());
|
||||
ReflectionHelpers.setField(mAudioStreamMediaService, "mBase", mContext);
|
||||
when(mAudioStreamMediaService.getSystemService(anyString()))
|
||||
.thenReturn(mMediaSessionManager);
|
||||
when(mMediaSessionManager.createSession(any(), anyString(), any())).thenReturn(mISession);
|
||||
try {
|
||||
when(mISession.getController()).thenReturn(mISessionController);
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
doReturn(mNotificationManager)
|
||||
.when(mAudioStreamMediaService)
|
||||
.getSystemService(NotificationManager.class);
|
||||
when(mAudioStreamMediaService.getApplicationInfo()).thenReturn(new ApplicationInfo());
|
||||
when(mAudioStreamMediaService.getResources()).thenReturn(mResources);
|
||||
when(mAudioStreamMediaService.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
|
||||
mDisplayMetrics.density = 1.5f;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mAudioStreamMediaService.stopSelf();
|
||||
ShadowBluetoothUtils.reset();
|
||||
ShadowAudioStreamsHelper.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
|
||||
mAudioStreamMediaService.onCreate();
|
||||
|
||||
verify(mNotificationManager, never()).createNotificationChannel(any());
|
||||
verify(mBluetoothEventManager, never()).registerCallback(any());
|
||||
verify(mLeBroadcastAssistant, never()).registerServiceCallBack(any(), any());
|
||||
verify(mVolumeControlProfile, never()).registerCallback(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_flagOn_init() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
|
||||
mAudioStreamMediaService.onCreate();
|
||||
|
||||
verify(mNotificationManager).createNotificationChannel(any());
|
||||
verify(mBluetoothEventManager).registerCallback(any());
|
||||
verify(mLeBroadcastAssistant).registerServiceCallBack(any(), any());
|
||||
verify(mVolumeControlProfile).registerCallback(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
|
||||
mAudioStreamMediaService.onCreate();
|
||||
mAudioStreamMediaService.onDestroy();
|
||||
|
||||
verify(mBluetoothEventManager, never()).unregisterCallback(any());
|
||||
verify(mLeBroadcastAssistant, never()).unregisterServiceCallBack(any());
|
||||
verify(mVolumeControlProfile, never()).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_flagOn_cleanup() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
|
||||
mAudioStreamMediaService.onCreate();
|
||||
mAudioStreamMediaService.onDestroy();
|
||||
|
||||
verify(mBluetoothEventManager).unregisterCallback(any());
|
||||
verify(mLeBroadcastAssistant).unregisterServiceCallBack(any());
|
||||
verify(mVolumeControlProfile).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartCommand_noBroadcastId_stopSelf() {
|
||||
mAudioStreamMediaService.onStartCommand(new Intent(), /* flags= */ 0, /* startId= */ 0);
|
||||
|
||||
assertThat(mAudioStreamMediaService.mLocalSession).isNull();
|
||||
verify(mAudioStreamMediaService).stopSelf();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartCommand_noDevice_stopSelf() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(BROADCAST_ID, 1);
|
||||
|
||||
mAudioStreamMediaService.onStartCommand(intent, /* flags= */ 0, /* startId= */ 0);
|
||||
|
||||
assertThat(mAudioStreamMediaService.mLocalSession).isNull();
|
||||
verify(mAudioStreamMediaService).stopSelf();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartCommand_createSessionAndStartForeground() {
|
||||
var devices = new ArrayList<BluetoothDevice>();
|
||||
devices.add(mDevice);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(BROADCAST_ID, 1);
|
||||
intent.putParcelableArrayListExtra(DEVICES, devices);
|
||||
|
||||
mAudioStreamMediaService.onStartCommand(intent, /* flags= */ 0, /* startId= */ 0);
|
||||
|
||||
assertThat(mAudioStreamMediaService.mLocalSession).isNotNull();
|
||||
verify(mAudioStreamMediaService, never()).stopSelf();
|
||||
|
||||
ArgumentCaptor<Notification> notification = ArgumentCaptor.forClass(Notification.class);
|
||||
verify(mAudioStreamMediaService).startForeground(anyInt(), notification.capture());
|
||||
assertThat(notification.getValue().getSmallIcon()).isNotNull();
|
||||
assertThat(notification.getValue().isStyle(Notification.MediaStyle.class)).isTrue();
|
||||
}
|
||||
}
|
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.bluetooth.Utils;
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import org.junit.After;
|
||||
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 org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowBluetoothAdapter.class,
|
||||
ShadowBluetoothUtils.class,
|
||||
ShadowAudioStreamsHelper.class,
|
||||
})
|
||||
public class AudioStreamsCategoryControllerTest {
|
||||
private static final String KEY = "audio_streams_settings_category";
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private LocalBluetoothProfileManager mBtProfileManager;
|
||||
@Mock private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock private LocalBluetoothLeBroadcast mBroadcast;
|
||||
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock private VolumeControlProfile mVolumeControl;
|
||||
@Mock private PreferenceScreen mScreen;
|
||||
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
||||
@Mock private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
|
||||
private AudioStreamsCategoryController mController;
|
||||
private Lifecycle mLifecycle;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private Preference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
|
||||
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mBtProfileManager);
|
||||
when(mBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||
when(mBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
||||
when(mBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
|
||||
when(mBroadcast.isProfileReady()).thenReturn(true);
|
||||
when(mAssistant.isProfileReady()).thenReturn(true);
|
||||
when(mVolumeControl.isProfileReady()).thenReturn(true);
|
||||
mController = new AudioStreamsCategoryController(mContext, KEY);
|
||||
mPreference = new Preference(mContext);
|
||||
when(mScreen.findPreference(KEY)).thenReturn(mPreference);
|
||||
mController.displayPreference(mScreen);
|
||||
mPreference.setVisible(false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowAudioStreamsHelper.reset();
|
||||
ShadowBluetoothUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagOn() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagOff() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager, never()).registerCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_flagOn_registerCallback() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager).registerCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager, never()).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_flagOn_unregisterCallback() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_flagOff_invisible() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_noConnectedLe_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isNotProfileReady_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
when(mVolumeControl.isProfileReady()).thenReturn(false);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isBroadcasting_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
when(mBroadcast.isEnabled(any())).thenReturn(true);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isBluetoothOff_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
mShadowBluetoothAdapter.setEnabled(false);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_visible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isTrue();
|
||||
}
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsDashboardFragment.KEY_BROADCAST_METADATA;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsScanQrCodeController.REQUEST_SCAN_BT_BROADCAST_QR_CODE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioStreamsDashboardFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
private static final String VALID_METADATA =
|
||||
"BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
|
||||
+ "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
|
||||
|
||||
private Context mContext;
|
||||
private AudioStreamsProgressCategoryController mController;
|
||||
private TestFragment mTestFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mTestFragment = spy(new TestFragment());
|
||||
doReturn(mContext).when(mTestFragment).getContext();
|
||||
mController = spy(new AudioStreamsProgressCategoryController(mContext, "key"));
|
||||
doReturn(mController).when(mTestFragment).use(AudioStreamsProgressCategoryController.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferenceScreenResId_returnsCorrectXml() {
|
||||
assertThat(mTestFragment.getPreferenceScreenResId())
|
||||
.isEqualTo(R.xml.bluetooth_le_audio_streams);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLogTag_returnsCorrectTag() {
|
||||
assertThat(mTestFragment.getLogTag()).isEqualTo("AudioStreamsDashboardFrag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHelpResource_returnsCorrectResource() {
|
||||
assertThat(mTestFragment.getHelpResource()).isEqualTo(R.string.help_url_audio_sharing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_invalidRequestCode_doNothing() {
|
||||
mTestFragment.onAttach(mContext);
|
||||
|
||||
mTestFragment.onActivityResult(0, 0, null);
|
||||
verify(mController, never()).setSourceFromQrCode(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_invalidRequestResult_doNothing() {
|
||||
mTestFragment.onAttach(mContext);
|
||||
|
||||
mTestFragment.onActivityResult(REQUEST_SCAN_BT_BROADCAST_QR_CODE, 0, null);
|
||||
verify(mController, never()).setSourceFromQrCode(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_nullData_doNothing() {
|
||||
mTestFragment.onAttach(mContext);
|
||||
|
||||
mTestFragment.onActivityResult(REQUEST_SCAN_BT_BROADCAST_QR_CODE, Activity.RESULT_OK, null);
|
||||
verify(mController, never()).setSourceFromQrCode(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_setSourceFromQrCode() {
|
||||
mTestFragment.onAttach(mContext);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(KEY_BROADCAST_METADATA, VALID_METADATA);
|
||||
|
||||
mTestFragment.onActivityResult(
|
||||
REQUEST_SCAN_BT_BROADCAST_QR_CODE, Activity.RESULT_OK, intent);
|
||||
verify(mController).setSourceFromQrCode(any(), any());
|
||||
}
|
||||
|
||||
public static class TestFragment extends AudioStreamsDashboardFragment {
|
||||
@Override
|
||||
protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
|
||||
return super.use(clazz);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.when;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
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;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioStreamsProgressCategoryPreferenceTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Mock PreferenceManager mPreferenceManager;
|
||||
private Context mContext;
|
||||
private AudioStreamsProgressCategoryPreference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mPreference = spy(new AudioStreamsProgressCategoryPreference(mContext));
|
||||
when(mPreference.getPreferenceManager()).thenReturn(mPreferenceManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAudioStreamPreference_singlePreference() {
|
||||
AudioStreamPreference first = new AudioStreamPreference(mContext, null);
|
||||
mPreference.addAudioStreamPreference(first, (p1, p2) -> 0);
|
||||
|
||||
assertThat(mPreference.getPreferenceCount()).isEqualTo(1);
|
||||
assertThat(mPreference.getPreference(0)).isEqualTo(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAudioStreamPreference_multiPreference_sorted() {
|
||||
Comparator<AudioStreamPreference> c =
|
||||
Comparator.comparingInt(AudioStreamPreference::getOrder);
|
||||
AudioStreamPreference first = new AudioStreamPreference(mContext, null);
|
||||
first.setOrder(1);
|
||||
AudioStreamPreference second = new AudioStreamPreference(mContext, null);
|
||||
second.setOrder(0);
|
||||
mPreference.addAudioStreamPreference(first, c);
|
||||
mPreference.addAudioStreamPreference(second, c);
|
||||
|
||||
assertThat(mPreference.getPreferenceCount()).isEqualTo(2);
|
||||
assertThat(mPreference.getPreference(0)).isEqualTo(second);
|
||||
assertThat(mPreference.getPreference(1)).isEqualTo(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAudioStreamPreferences_shouldBeEmpty() {
|
||||
Comparator<AudioStreamPreference> c =
|
||||
Comparator.comparingInt(AudioStreamPreference::getOrder);
|
||||
AudioStreamPreference first = new AudioStreamPreference(mContext, null);
|
||||
first.setOrder(0);
|
||||
AudioStreamPreference second = new AudioStreamPreference(mContext, null);
|
||||
second.setOrder(1);
|
||||
mPreference.addAudioStreamPreference(first, c);
|
||||
mPreference.addAudioStreamPreference(second, c);
|
||||
mPreference.removeAudioStreamPreferences();
|
||||
|
||||
assertThat(mPreference.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioStreamsRepositoryTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
private static final String METADATA_STR =
|
||||
"BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
|
||||
+ "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
|
||||
private static final String TEST_SHARED_PREFERENCE = "AudioStreamsRepositoryTestPref";
|
||||
private final BluetoothLeBroadcastMetadata mMetadata =
|
||||
BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(METADATA_STR);
|
||||
private Context mContext;
|
||||
private AudioStreamsRepository mAudioStreamsRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
doReturn(getSharedPreferences()).when(mContext).getSharedPreferences(anyString(), anyInt());
|
||||
mAudioStreamsRepository = AudioStreamsRepository.getInstance();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheAndGetMetadata_sameId() {
|
||||
mAudioStreamsRepository.cacheMetadata(mMetadata);
|
||||
|
||||
assertThat(mMetadata).isNotNull();
|
||||
assertThat(mAudioStreamsRepository.getCachedMetadata(mMetadata.getBroadcastId()))
|
||||
.isEqualTo(mMetadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheAndGetMetadata_differentId() {
|
||||
mAudioStreamsRepository.cacheMetadata(mMetadata);
|
||||
|
||||
assertThat(mMetadata).isNotNull();
|
||||
assertThat(mAudioStreamsRepository.getCachedMetadata(1)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAndGetMetadata_sameId() {
|
||||
mAudioStreamsRepository.saveMetadata(mContext, mMetadata);
|
||||
|
||||
assertThat(mMetadata).isNotNull();
|
||||
assertThat(mAudioStreamsRepository.getSavedMetadata(mContext, mMetadata.getBroadcastId()))
|
||||
.isEqualTo(mMetadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAndGetMetadata_differentId() {
|
||||
mAudioStreamsRepository.saveMetadata(mContext, mMetadata);
|
||||
|
||||
assertThat(mMetadata).isNotNull();
|
||||
assertThat(mAudioStreamsRepository.getSavedMetadata(mContext, 1)).isNull();
|
||||
}
|
||||
|
||||
private SharedPreferences getSharedPreferences() {
|
||||
return mContext.getSharedPreferences(TEST_SHARED_PREFERENCE, Context.MODE_PRIVATE);
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsHelper;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
@@ -63,4 +64,9 @@ public class ShadowAudioStreamsHelper {
|
||||
LocalBluetoothManager manager) {
|
||||
return Optional.ofNullable(sCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public LocalBluetoothLeBroadcastAssistant getLeBroadcastAssistant() {
|
||||
return sMockHelper.getLeBroadcastAssistant();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user