feat: SettingsLib验证通过-使用App module启用
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.car.ui.preference.CarUiPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothAddressPreferenceControllerTest {
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private BluetoothAddressPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private CarUiPreference mPreference;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
mPreference = new CarUiPreference(mContext);
|
||||
mPreferenceController = new BluetoothAddressPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions,
|
||||
mBluetoothAdapter);
|
||||
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_setsAddress() {
|
||||
String address = "address";
|
||||
when(mBluetoothAdapter.getAddress()).thenReturn(address);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(
|
||||
mContext.getString(R.string.bluetooth_vehicle_mac_address, address));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.MultiActionPreference;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.common.ToggleButtonActionItem;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothBondedDevicesPreferenceControllerTest {
|
||||
private static final String TEST_RESTRICTION = UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private BluetoothBondedDevicesPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private LocalBluetoothProfile mPhoneProfile;
|
||||
private LocalBluetoothProfile mMediaProfile;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private Collection<CachedBluetoothDevice> mCachedDevices;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mBondedCachedDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mBondedDevice;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock
|
||||
private LocalBluetoothAdapter mLocalBluetoothAdapter;
|
||||
@Mock
|
||||
private Toast mMockToast;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
mSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(Toast.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
ExtendedMockito.when(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mMockToast);
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
Context mSpiedContext = spy(mContext);
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
when(mBondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBondedCachedDevice.getDevice()).thenReturn(mBondedDevice);
|
||||
|
||||
mPhoneProfile =
|
||||
new BluetoothTestUtils.TestLocalBluetoothProfile(BluetoothProfile.HEADSET_CLIENT);
|
||||
mMediaProfile =
|
||||
new BluetoothTestUtils.TestLocalBluetoothProfile(BluetoothProfile.A2DP_SINK);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(List.of(mPhoneProfile, mMediaProfile));
|
||||
|
||||
BluetoothDevice unbondedDevice = mock(BluetoothDevice.class);
|
||||
when(unbondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
CachedBluetoothDevice unbondedCachedDevice = mock(CachedBluetoothDevice.class);
|
||||
when(unbondedCachedDevice.getDevice()).thenReturn(unbondedDevice);
|
||||
|
||||
mCachedDevices = Arrays.asList(mBondedCachedDevice, unbondedCachedDevice);
|
||||
|
||||
mLocalBluetoothManager = spy(BluetoothUtils.getLocalBtManager(mSpiedContext));
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
|
||||
when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
|
||||
when(mLocalBluetoothAdapter.getBondedDevices()).thenReturn(Set.of(mBondedDevice));
|
||||
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mSpiedContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mSpiedContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mSpiedContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
mPreferenceController = new BluetoothBondedDevicesPreferenceController(mSpiedContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions,
|
||||
mLocalBluetoothManager, mUserManager);
|
||||
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showsOnlyBondedDevices() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(devicePreference.getCachedDevice()).isEqualTo(mBondedCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_refreshesUi() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
|
||||
// Unbond the only bonded device.
|
||||
when(mBondedCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mBondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mLocalBluetoothAdapter.getBondedDevices()).thenReturn(Set.of());
|
||||
mPreferenceController.onDeviceBondStateChanged(mBondedCachedDevice,
|
||||
BluetoothDevice.BOND_NONE);
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void onDeviceClicked_connected_launchesDeviceDetailsFragment() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mFragmentController).launchFragment(
|
||||
any(BluetoothDeviceDetailsFragment.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bluetoothButtonClicked_connected_disconnectsFromDevice() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
ToggleButtonActionItem bluetoothButton = devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM1);
|
||||
assertThat(bluetoothButton.isVisible()).isTrue();
|
||||
bluetoothButton.onClick();
|
||||
|
||||
verify(mBondedCachedDevice).disconnect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bluetoothButtonClicked_notConnected_connectsToDevice() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(false);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
ToggleButtonActionItem bluetoothButton = devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM1);
|
||||
assertThat(bluetoothButton.isEnabled()).isTrue();
|
||||
bluetoothButton.onClick();
|
||||
|
||||
verify(mBondedCachedDevice).connect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void phoneButtonClicked_phoneProfile_enabled() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
ToggleButtonActionItem phoneButton = devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM2);
|
||||
assertThat(phoneButton.isEnabled()).isTrue();
|
||||
assertThat(mPhoneProfile.isEnabled(mBondedDevice)).isFalse();
|
||||
phoneButton.onClick();
|
||||
|
||||
assertThat(mPhoneProfile.isEnabled(mBondedDevice)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediaButtonClicked_mediaProfile_enabled() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
ToggleButtonActionItem mediaButton = devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM3);
|
||||
mediaButton.onClick();
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(mMediaProfile.isEnabled(mBondedDevice)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actionButtons_disallowConfigBluetooth_bluetoothActionStaysDisabled() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM1).isEnabled()).isTrue();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM2).isEnabled()).isFalse();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM3).isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsChanged_hasRestrictions_actionButtonDisabled() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(restrictions);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM1).isEnabled()).isTrue();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM2).isEnabled()).isFalse();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM3).isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsChanged_restrictionToggled_actionButtonsEnabled() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(restrictions);
|
||||
|
||||
CarUxRestrictions noRestrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_BASELINE, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(noRestrictions);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM1).isEnabled()).isTrue();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM2).isEnabled()).isTrue();
|
||||
assertThat(devicePreference.getActionItem(
|
||||
MultiActionPreference.ActionItem.ACTION_ITEM3).isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsNoSetup_phoneItemClicked_showsToast() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(restrictions);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
// Due to the limitations of the testing environment, onBindViewHolder() is never called and
|
||||
// thus certain fields are never set. Manually set it here.
|
||||
ToggleButtonActionItem phoneItem =
|
||||
devicePreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM2);
|
||||
String toastText = mContext.getResources()
|
||||
.getString(R.string.car_ui_restricted_while_driving);
|
||||
phoneItem.setRestrictedOnClickListener(p -> Toast.makeText(mContext, toastText,
|
||||
Toast.LENGTH_LONG).show());
|
||||
phoneItem.setPreference(devicePreference);
|
||||
|
||||
phoneItem.onClick();
|
||||
|
||||
ExtendedMockito.verify(() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsNoSetup_mediaItemClicked_showsToast() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(restrictions);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
// Due to the limitations of the testing environment, onBindViewHolder() is never called and
|
||||
// thus certain fields are never set. Manually set them here.
|
||||
ToggleButtonActionItem mediaItem =
|
||||
devicePreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM3);
|
||||
String toastText = mContext.getResources()
|
||||
.getString(R.string.car_ui_restricted_while_driving);
|
||||
mediaItem.setRestrictedOnClickListener(p -> Toast.makeText(mContext, toastText,
|
||||
Toast.LENGTH_LONG).show());
|
||||
mediaItem.setPreference(devicePreference);
|
||||
|
||||
mediaItem.onClick();
|
||||
|
||||
ExtendedMockito.verify(() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsDisallowConfigBluetooth_phoneItemClicked_showsToast() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
String toastText = mContext.getResources().getString(R.string.action_unavailable);
|
||||
|
||||
devicePreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM2).onClick();
|
||||
|
||||
ExtendedMockito.verify(() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUxRestrictionsDisallowConfigBluetooth_mediaItemClicked_showsToast() {
|
||||
when(mBondedCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mUserManager.hasUserRestriction(TEST_RESTRICTION)).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
String toastText = mContext.getResources().getString(R.string.action_unavailable);
|
||||
|
||||
devicePreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM3).onClick();
|
||||
|
||||
ExtendedMockito.verify(() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.car.settings.bluetooth;
|
||||
|
||||
import static com.android.car.settings.common.ActionButtonsPreference.ActionButtons;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.ActionButtonInfo;
|
||||
import com.android.car.settings.common.ActionButtonsPreference;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.ResourceTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDeviceActionButtonsPreferenceControllerTest {
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ActionButtonsPreference mActionButtonsPreference;
|
||||
private BluetoothDeviceActionButtonsPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
String address = "00:11:22:33:AA:BB";
|
||||
when(mCachedDevice.getAddress()).thenReturn(address);
|
||||
|
||||
mActionButtonsPreference = new ActionButtonsPreference(mContext);
|
||||
mPreferenceController = new BluetoothDeviceActionButtonsPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
|
||||
mPreferenceController.setCachedDevice(mCachedDevice);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController,
|
||||
mActionButtonsPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forgetButtonClicked_unpairsDevice() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
findForgetButton().getOnClickListener().onClick(/* view= */ null);
|
||||
|
||||
verify(mCachedDevice).unpair();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forgetButtonClicked_goesBack() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
findForgetButton().getOnClickListener().onClick(/* view= */ null);
|
||||
|
||||
verify(mFragmentController).goBack();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionButtonClicked_deviceConnected_disconnectsDevice() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
findConnectionButton().getOnClickListener().onClick(/* view= */ null);
|
||||
|
||||
verify(mCachedDevice).disconnect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionButtonClicked_deviceNotConnected_connectsDevice() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
findConnectionButton().getOnClickListener().onClick(/* view= */ null);
|
||||
|
||||
verify(mCachedDevice).connect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceConnected_connectionButtonShowsDisconnect() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(findConnectionButton().getText()).isEqualTo(
|
||||
ResourceTestUtils.getString(mContext, "disconnect"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceNotConnected_connectionButtonShowsConnect() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(findConnectionButton().getText()).isEqualTo(
|
||||
ResourceTestUtils.getString(mContext, "connect"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceBusy_connectionButtonDisabled() {
|
||||
when(mCachedDevice.isBusy()).thenReturn(true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(findConnectionButton().isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceNotBusy_connectionButtonEnabled() {
|
||||
when(mCachedDevice.isBusy()).thenReturn(false);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(findConnectionButton().isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceAttributesChanged_updatesConnectionButtonState() {
|
||||
when(mCachedDevice.isBusy()).thenReturn(true);
|
||||
ArgumentCaptor<CachedBluetoothDevice.Callback> callbackCaptor = ArgumentCaptor.forClass(
|
||||
CachedBluetoothDevice.Callback.class);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
assertThat(findConnectionButton().isEnabled()).isFalse();
|
||||
verify(mCachedDevice).registerCallback(callbackCaptor.capture());
|
||||
|
||||
when(mCachedDevice.isBusy()).thenReturn(false);
|
||||
callbackCaptor.getValue().onDeviceAttributesChanged();
|
||||
|
||||
assertThat(findConnectionButton().isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
private ActionButtonInfo findForgetButton() {
|
||||
return mActionButtonsPreference.getButton(ActionButtons.BUTTON2);
|
||||
}
|
||||
|
||||
private ActionButtonInfo findConnectionButton() {
|
||||
return mActionButtonsPreference.getButton(ActionButtons.BUTTON1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.car.ui.preference.CarUiPreference;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDeviceAddressPreferenceControllerTest {
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private BluetoothDeviceAddressPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private CarUiPreference mPreference;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
mPreference = new CarUiPreference(mContext);
|
||||
mPreferenceController = new BluetoothDeviceAddressPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
|
||||
mPreferenceController.setCachedDevice(mCachedBluetoothDevice);
|
||||
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_setsAddress() {
|
||||
String address = "address";
|
||||
when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(
|
||||
mContext.getString(R.string.bluetooth_device_mac_address, address));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDeviceNamePreferenceControllerTest {
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private BluetoothDeviceNamePreferenceController mPreferenceController;
|
||||
private Preference mPreference;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
|
||||
private BluetoothClass createBtClass(int deviceClass) {
|
||||
Parcel p = Parcel.obtain();
|
||||
p.writeInt(deviceClass);
|
||||
p.setDataPosition(0); // reset position of parcel before passing to constructor
|
||||
|
||||
BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
|
||||
p.recycle();
|
||||
return bluetoothClass;
|
||||
}
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
mPreference = new Preference(mContext);
|
||||
mPreference.setSelectable(true);
|
||||
mPreferenceController = new TestBluetoothDeviceNamePreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
|
||||
mPreferenceController.setCachedDevice(mCachedDevice);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_setsDeviceNameAsTitle() {
|
||||
String name = "name";
|
||||
when(mCachedDevice.getName()).thenReturn(name);
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreference.getTitle()).isEqualTo(name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_connected_setsCarConnectionSummaryAsSummary() {
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mCachedDevice.getCarConnectionSummary()).thenReturn(summary);
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_notConnectedsetsCarConnectionSummaryAsSummary() {
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.isConnected()).thenReturn(false);
|
||||
when(mCachedDevice.getCarConnectionSummary()).thenReturn(summary);
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_setsIcon() {
|
||||
when(mCachedDevice.getBtClass()).thenReturn(
|
||||
createBtClass(BluetoothClass.Device.Major.PHONE));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreference.getIcon()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_hearingAidDevice_setsBatteryStatusesAsSummary() {
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
when(mCachedDevice.getCarConnectionSummary()).thenReturn(summary);
|
||||
String otherSummary = "other summary";
|
||||
when(mCachedDeviceManager.getSubDeviceSummary(mCachedDevice)).thenReturn("other summary");
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
String expected = new StringJoiner(System.lineSeparator()).add(summary).add(
|
||||
otherSummary).toString();
|
||||
assertThat(mPreference.getSummary()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_launchesRenameDialog() {
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mPreference.performClick();
|
||||
|
||||
verify(mFragmentController).showDialog(any(RemoteRenameDialogFragment.class),
|
||||
eq(RemoteRenameDialogFragment.TAG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_handled() {
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreference.getOnPreferenceClickListener()
|
||||
.onPreferenceClick(mPreference)).isTrue();
|
||||
}
|
||||
|
||||
private class TestBluetoothDeviceNamePreferenceController
|
||||
extends BluetoothDeviceNamePreferenceController {
|
||||
|
||||
TestBluetoothDeviceNamePreferenceController(Context context, String preferenceKey,
|
||||
FragmentController fragmentController,
|
||||
CarUxRestrictions uxRestrictions) {
|
||||
super(context, preferenceKey, fragmentController, uxRestrictions);
|
||||
}
|
||||
|
||||
@Override
|
||||
CachedBluetoothDeviceManager getCachedDeviceManager() {
|
||||
return mCachedDeviceManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.testutils.BaseCarSettingsTestActivity;
|
||||
import com.android.car.ui.toolbar.ToolbarController;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
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.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDevicePickerFragmentTest {
|
||||
private BluetoothDevicePickerFragment mFragment;
|
||||
private BaseCarSettingsTestActivity mActivity;
|
||||
private FragmentManager mFragmentManager;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private LocalBluetoothManager mMockManager;
|
||||
@Mock
|
||||
private BluetoothEventManager mMockEventManager;
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<BaseCarSettingsTestActivity> mActivityTestRule =
|
||||
new ActivityTestRule<>(BaseCarSettingsTestActivity.class);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Throwable {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager();
|
||||
|
||||
mSession = ExtendedMockito.mockitoSession().mockStatic(
|
||||
BluetoothUtils.class, withSettings().lenient()).startMocking();
|
||||
when(BluetoothUtils.getLocalBtManager(any())).thenReturn(
|
||||
mMockManager);
|
||||
when(mMockManager.getEventManager()).thenReturn(mMockEventManager);
|
||||
CachedBluetoothDeviceManager cbdm = mock(CachedBluetoothDeviceManager.class);
|
||||
when(mMockManager.getCachedDeviceManager()).thenReturn(cbdm);
|
||||
setUpFragment();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_setsBluetoothManagerForegroundActivity() {
|
||||
verify(mMockManager).setForegroundActivity(mFragment.requireActivity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_showsProgressBar() {
|
||||
ToolbarController toolbar = mActivity.getToolbar();
|
||||
|
||||
assertThat(toolbar.getProgressBar().isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_clearsBluetoothManagerForegroundActivity() throws Throwable {
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.onStop();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockManager).setForegroundActivity(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_hidesProgressBar() throws Throwable {
|
||||
ToolbarController toolbar = mActivity.getToolbar();
|
||||
toolbar.getProgressBar().setVisible(true);
|
||||
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.onStop();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(toolbar.getProgressBar().isVisible()).isFalse();
|
||||
}
|
||||
|
||||
private void setUpFragment() throws Throwable {
|
||||
String bluetoothDevicePickerFragmentTag = "bluetooth_device_picker_fragment";
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_container, new BluetoothDevicePickerFragment(),
|
||||
bluetoothDevicePickerFragmentTag)
|
||||
.commitNow();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
mFragment = (BluetoothDevicePickerFragment)
|
||||
mFragmentManager.findFragmentByTag(bluetoothDevicePickerFragmentTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothDevicePicker;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelUuid;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDevicePickerPreferenceControllerTest {
|
||||
private static final String ALLOWED_LAUNCH_PACKAGE = "com.android.car.settings.tests.unit";
|
||||
private static final String DEFAULT_LAUNCH_PACKAGE = "test.package";
|
||||
private static final String DEFAULT_LAUNCH_CLASS = "TestClass";
|
||||
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private BluetoothDevicePickerPreferenceController mPreferenceController;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock
|
||||
private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mUnbondedCachedDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mUnbondedDevice;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mBondedCachedDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mBondedDevice;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock
|
||||
private BluetoothAdapter mMockBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
when(mUnbondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mUnbondedCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mUnbondedCachedDevice.getDevice()).thenReturn(mUnbondedDevice);
|
||||
when(mBondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBondedCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBondedCachedDevice.getDevice()).thenReturn(mBondedDevice);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||
Arrays.asList(mUnbondedCachedDevice, mBondedCachedDevice));
|
||||
// Make bonded device appear first in the list.
|
||||
when(mBondedCachedDevice.compareTo(mUnbondedCachedDevice)).thenReturn(-1);
|
||||
when(mUnbondedCachedDevice.compareTo(mBondedCachedDevice)).thenReturn(1);
|
||||
|
||||
mSession = ExtendedMockito.mockitoSession()
|
||||
.mockStatic(BluetoothUtils.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
when(BluetoothUtils.getLocalBtManager(mContext)).thenReturn(mLocalBluetoothManager);
|
||||
when(BluetoothUtils.shouldEnableBTScanning(eq(mContext), any())).thenReturn(true);
|
||||
BluetoothManager bluetoothManager = mock(BluetoothManager.class);
|
||||
when(bluetoothManager.getAdapter()).thenReturn(mMockBluetoothAdapter);
|
||||
when(mContext.getSystemService(BluetoothManager.class)).thenReturn(bluetoothManager);
|
||||
|
||||
mPreferenceController = new TestBluetoothDevicePickerPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController,
|
||||
mCarUxRestrictions);
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkInitialized_noLaunchIntentSet_throwsIllegalStateException() {
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
|
||||
mPreferenceGroup));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_appliesFilterType() {
|
||||
// Setup device to pass the filter.
|
||||
when(mBondedDevice.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.A2DP_SINK});
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ false,
|
||||
BluetoothDevicePicker.FILTER_TYPE_AUDIO, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
assertThat(((BluetoothDevicePreference) mPreferenceGroup.getPreference(
|
||||
0)).getCachedDevice()).isEqualTo(mBondedCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_callingPackageEqualToLaunchPackage_setsClassName() {
|
||||
ComponentName component = new ComponentName(ALLOWED_LAUNCH_PACKAGE, DEFAULT_LAUNCH_CLASS);
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, component.getPackageName(),
|
||||
component.getClassName());
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).sendBroadcast(captor.capture());
|
||||
Intent pickedIntent = captor.getValue();
|
||||
assertThat(pickedIntent.getAction()).isEqualTo(
|
||||
BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
||||
assertThat(pickedIntent.getComponent()).isEqualTo(component);
|
||||
assertThat((BluetoothDevice) pickedIntent.getParcelableExtra(
|
||||
BluetoothDevice.EXTRA_DEVICE)).isEqualTo(mBondedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_callingPackageNotEqualToLaunchPackage_doesNotSetClassName() {
|
||||
ComponentName component = new ComponentName(DEFAULT_LAUNCH_PACKAGE, DEFAULT_LAUNCH_CLASS);
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, component.getPackageName(),
|
||||
component.getClassName());
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).sendBroadcast(captor.capture());
|
||||
Intent pickedIntent = captor.getValue();
|
||||
assertThat(pickedIntent.getAction()).isEqualTo(
|
||||
BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
||||
assertThat(pickedIntent.getComponent()).isEqualTo(null);
|
||||
assertThat((BluetoothDevice) pickedIntent.getParcelableExtra(
|
||||
BluetoothDevice.EXTRA_DEVICE)).isEqualTo(mBondedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_bondedDevice_goesBack() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mFragmentController).goBack();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_unbondedDevice_doesNotNeedAuth_sendsPickedIntent() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ false,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(1);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).sendBroadcast(captor.capture());
|
||||
Intent pickedIntent = captor.getValue();
|
||||
assertThat(pickedIntent.getAction()).isEqualTo(
|
||||
BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_unbondedDevice_needsAuth_startsPairing() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(1);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mUnbondedCachedDevice).startPairing();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_unbondedDevice_needsAuth_pairingStartFails_resumesScanning() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
verify(mMockBluetoothAdapter).startDiscovery();
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(1);
|
||||
when(mUnbondedCachedDevice.startPairing()).thenReturn(false);
|
||||
|
||||
Mockito.clearInvocations(mMockBluetoothAdapter);
|
||||
devicePreference.performClick();
|
||||
InOrder inOrder = inOrder(mMockBluetoothAdapter);
|
||||
inOrder.verify(mMockBluetoothAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
|
||||
inOrder.verify(mMockBluetoothAdapter).startDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_selectedDeviceBonded_sendsPickedIntent() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(1);
|
||||
|
||||
// Select device.
|
||||
devicePreference.performClick();
|
||||
// Device bonds.
|
||||
mPreferenceController.onDeviceBondStateChanged(
|
||||
devicePreference.getCachedDevice(), BluetoothDevice.BOND_BONDED);
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).sendBroadcast(captor.capture());
|
||||
Intent pickedIntent = captor.getValue();
|
||||
assertThat(pickedIntent.getAction()).isEqualTo(
|
||||
BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_selectedDeviceBonded_goesBack() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(1);
|
||||
|
||||
// Select device.
|
||||
devicePreference.performClick();
|
||||
// Device bonds.
|
||||
mPreferenceController.onDeviceBondStateChanged(
|
||||
devicePreference.getCachedDevice(), BluetoothDevice.BOND_BONDED);
|
||||
|
||||
verify(mFragmentController).goBack();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_noDeviceSelected_sendsNullPickedIntent() {
|
||||
Intent launchIntent = createLaunchIntent(/* needsAuth= */ true,
|
||||
BluetoothDevicePicker.FILTER_TYPE_ALL, DEFAULT_LAUNCH_PACKAGE,
|
||||
DEFAULT_LAUNCH_CLASS);
|
||||
mPreferenceController.setLaunchIntent(launchIntent);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.onDestroy(mLifecycleOwner);
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).sendBroadcast(captor.capture());
|
||||
Intent pickedIntent = captor.getValue();
|
||||
assertThat(pickedIntent.getAction()).isEqualTo(
|
||||
BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
||||
assertThat((BluetoothDevice) pickedIntent.getParcelableExtra(
|
||||
BluetoothDevice.EXTRA_DEVICE)).isNull();
|
||||
}
|
||||
|
||||
private Intent createLaunchIntent(boolean needAuth, int filterType, String packageName,
|
||||
String className) {
|
||||
Intent intent = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
|
||||
intent.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, needAuth);
|
||||
intent.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE, filterType);
|
||||
intent.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE, packageName);
|
||||
intent.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS, className);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private static class TestBluetoothDevicePickerPreferenceController
|
||||
extends BluetoothDevicePickerPreferenceController {
|
||||
|
||||
TestBluetoothDevicePickerPreferenceController(Context context, String preferenceKey,
|
||||
FragmentController fragmentController,
|
||||
CarUxRestrictions uxRestrictions) {
|
||||
super(context, preferenceKey, fragmentController, uxRestrictions);
|
||||
}
|
||||
|
||||
@Override
|
||||
String getCallingAppPackageName(IBinder activityToken) {
|
||||
return ALLOWED_LAUNCH_PACKAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.MultiActionPreference;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
|
||||
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 java.util.Collections;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDevicePreferenceTest {
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private BluetoothDevicePreference mPreference;
|
||||
|
||||
private BluetoothClass createBtClass(int deviceClass) {
|
||||
Parcel p = Parcel.obtain();
|
||||
p.writeInt(deviceClass);
|
||||
p.setDataPosition(0); // reset position of parcel before passing to constructor
|
||||
|
||||
BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
|
||||
p.recycle();
|
||||
return bluetoothClass;
|
||||
}
|
||||
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock
|
||||
private LocalBluetoothProfile mProfile;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actionIsHiddenByDefault() {
|
||||
assertThat(mPreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM1)
|
||||
.isVisible()).isFalse();
|
||||
assertThat(mPreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM1)
|
||||
.isVisible()).isFalse();
|
||||
assertThat(mPreference.getActionItem(MultiActionPreference.ActionItem.ACTION_ITEM1)
|
||||
.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_registersDeviceCallback() {
|
||||
mPreference.onAttached();
|
||||
|
||||
verify(mCachedDevice).registerCallback(any(CachedBluetoothDevice.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_setsDeviceNameAsTitle() {
|
||||
String name = "name";
|
||||
when(mCachedDevice.getName()).thenReturn(name);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.getTitle()).isEqualTo(name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_notConnected_setsCarConnectionSummaryAsSummary() {
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.isConnected()).thenReturn(false);
|
||||
when(mCachedDevice.getCarConnectionSummary(anyBoolean(), anyBoolean())).thenReturn(summary);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_connected_setsCarConnectionSummaryAsSummary() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.getCarConnectionSummary(anyBoolean(), anyBoolean())).thenReturn(summary);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_connected_carConnectionSummaryIsNull_setsSummary() {
|
||||
when(mCachedDevice.isConnected()).thenReturn(true);
|
||||
|
||||
String summary = "Summary";
|
||||
when(mCachedDevice.getCarConnectionSummary(anyBoolean(), anyBoolean())).thenReturn(summary);
|
||||
when(mCachedDevice.getProfiles()).thenReturn(Collections.singletonList(mProfile));
|
||||
when(mProfile.getDrawableResource(any()))
|
||||
.thenReturn(com.android.internal.R.drawable.ic_settings_bluetooth);
|
||||
mPreference.onAttached();
|
||||
|
||||
// Null device type descriptions aren't added to the summary when device is connected
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_setsIcon() {
|
||||
when(mCachedDevice.getBtClass()).thenReturn(
|
||||
createBtClass(BluetoothClass.Device.Major.PHONE));
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.getIcon()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_deviceNotBusy_setsEnabled() {
|
||||
when(mCachedDevice.isBusy()).thenReturn(false);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_deviceBusy_setsNotEnabled() {
|
||||
when(mCachedDevice.isBusy()).thenReturn(true);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_deviceNameNotHumanReadable_setsHidden() {
|
||||
SystemProperties.set("persist.bluetooth.showdeviceswithoutnames", Boolean.FALSE.toString());
|
||||
when(mCachedDevice.hasHumanReadableName()).thenReturn(false);
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedDevice);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttached_deviceNameNotHumanReadable_showWithoutNamesTrue_setsShown() {
|
||||
SystemProperties.set("persist.bluetooth.showdeviceswithoutnames", Boolean.TRUE.toString());
|
||||
when(mCachedDevice.hasHumanReadableName()).thenReturn(false);
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedDevice);
|
||||
|
||||
mPreference.onAttached();
|
||||
|
||||
assertThat(mPreference.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDetached_unregistersDeviceCallback() {
|
||||
ArgumentCaptor<CachedBluetoothDevice.Callback> callbackCaptor = ArgumentCaptor.forClass(
|
||||
CachedBluetoothDevice.Callback.class);
|
||||
mPreference.onAttached();
|
||||
verify(mCachedDevice).registerCallback(callbackCaptor.capture());
|
||||
|
||||
mPreference.onDetached();
|
||||
|
||||
verify(mCachedDevice).unregisterCallback(callbackCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceAttributesChanged_refreshesUi() {
|
||||
String name = "name";
|
||||
when(mCachedDevice.getName()).thenReturn(name);
|
||||
String summary = "summary";
|
||||
when(mCachedDevice.getCarConnectionSummary(anyBoolean(), anyBoolean())).thenReturn(summary);
|
||||
when(mCachedDevice.isBusy()).thenReturn(false);
|
||||
ArgumentCaptor<CachedBluetoothDevice.Callback> callbackCaptor = ArgumentCaptor.forClass(
|
||||
CachedBluetoothDevice.Callback.class);
|
||||
mPreference.onAttached();
|
||||
verify(mCachedDevice).registerCallback(callbackCaptor.capture());
|
||||
|
||||
assertThat(mPreference.getTitle()).isEqualTo(name);
|
||||
assertThat(mPreference.getSummary()).isEqualTo(summary);
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
|
||||
String updatedName = "updatedName";
|
||||
when(mCachedDevice.getName()).thenReturn(updatedName);
|
||||
String updatedSummary = "updatedSummary";
|
||||
when(mCachedDevice.getCarConnectionSummary(anyBoolean(), anyBoolean()))
|
||||
.thenReturn(updatedSummary);
|
||||
when(mCachedDevice.isBusy()).thenReturn(true);
|
||||
|
||||
callbackCaptor.getValue().onDeviceAttributesChanged();
|
||||
|
||||
assertThat(mPreference.getTitle()).isEqualTo(updatedName);
|
||||
assertThat(mPreference.getSummary()).isEqualTo(updatedSummary);
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_devicesEqual_returnsTrue() {
|
||||
BluetoothDevicePreference otherPreference = new BluetoothDevicePreference(mContext,
|
||||
mCachedDevice);
|
||||
|
||||
assertThat(mPreference.equals(otherPreference)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_devicesNotEqual_returnsFalse() {
|
||||
BluetoothDevicePreference otherPreference = new BluetoothDevicePreference(mContext,
|
||||
mock(CachedBluetoothDevice.class));
|
||||
|
||||
assertThat(mPreference.equals(otherPreference)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_sameType_usesDeviceCompareTo() {
|
||||
CachedBluetoothDevice otherDevice = mock(CachedBluetoothDevice.class);
|
||||
BluetoothDevicePreference otherPreference = new BluetoothDevicePreference(mContext,
|
||||
otherDevice);
|
||||
when(mCachedDevice.compareTo(otherDevice)).thenReturn(1);
|
||||
when(otherDevice.compareTo(mCachedDevice)).thenReturn(-1);
|
||||
|
||||
assertThat(mPreference.compareTo(otherPreference)).isEqualTo(1);
|
||||
assertThat(otherPreference.compareTo(mPreference)).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_differentType_fallsBackToDefaultCompare() {
|
||||
mPreference.setOrder(1);
|
||||
Preference otherPreference = new Preference(mContext);
|
||||
otherPreference.setOrder(2);
|
||||
|
||||
assertThat(mPreference.compareTo(otherPreference)).isEqualTo(-1);
|
||||
verify(mCachedDevice, never()).compareTo(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.car.settings.bluetooth;
|
||||
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
|
||||
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.android.car.settings.common.PreferenceController.DISABLED_FOR_PROFILE;
|
||||
import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG;
|
||||
|
||||
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.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.EnterpriseTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class BluetoothDeviceProfilesPreferenceControllerMockTest {
|
||||
private static final String TEST_RESTRICTION =
|
||||
android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private final LifecycleOwner mLifecycleOwner = new TestLifecycleOwner();
|
||||
|
||||
private BluetoothDeviceProfilesPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private BluetoothDevice mDevice;
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private UserManager mMockUserManager;
|
||||
@Mock
|
||||
private Toast mMockToast;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
mSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(Toast.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
|
||||
|
||||
when(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mMockToast);
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
when(mCachedDevice.getDevice()).thenReturn(mDevice);
|
||||
|
||||
LocalBluetoothProfile profile =
|
||||
new BluetoothTestUtils.TestLocalBluetoothProfile(BluetoothProfile.HEADSET_CLIENT);
|
||||
when(mCachedDevice.getProfiles()).thenReturn(List.of(profile));
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
mPreferenceController = new BluetoothDeviceProfilesPreferenceController(mContext,
|
||||
"key", mFragmentController, mCarUxRestrictions);
|
||||
|
||||
mPreferenceController.setCachedDevice(mCachedDevice);
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByUm_disabledForUser() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByUm_disabledForUser_zoneWrite() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("write");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByUm_disabledForUser_zoneRead() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("read");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByUm_disabledForUser_zoneHidden() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("hidden");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByDpm_disabledForUser() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE_FOR_VIEWING);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByDpm_disabledForUser_zoneWrite() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("write");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByDpm_disabledForUser_zoneRead() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("read");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByDpm_disabledForUser_zoneHidden() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("hidden");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_notRestricted_available() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_notRestricted_available_zoneWrite() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("write");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_notRestricted_available_zoneRead() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("read");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_notRestricted_available_zoneHidden() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.setAvailabilityStatusForZone("hidden");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testDisabledClick_restrictedByDpm_dialog() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
BluetoothDeviceProfilePreference pref =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
pref.performClick();
|
||||
|
||||
assertShowingDisabledByAdminDialog();
|
||||
}
|
||||
|
||||
private void assertShowingBlockedToast() {
|
||||
String toastText = mContext.getResources().getString(R.string.action_unavailable);
|
||||
ExtendedMockito.verify(
|
||||
() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
|
||||
private void assertShowingDisabledByAdminDialog() {
|
||||
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
|
||||
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothDeviceProfilesPreferenceControllerTest {
|
||||
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private BluetoothDeviceProfilesPreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mBondedCachedDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mBondedDevice;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private Toast mMockToast;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
mSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(Toast.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
ExtendedMockito.when(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mMockToast);
|
||||
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
mLocalBluetoothManager = spy(BluetoothUtils.getLocalBtManager(mContext));
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
mPreferenceController = new BluetoothDeviceProfilesPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions,
|
||||
mLocalBluetoothManager, mUserManager);
|
||||
|
||||
when(mBondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBondedCachedDevice.getDevice()).thenReturn(mBondedDevice);
|
||||
mPreferenceController.setCachedDevice(mBondedCachedDevice);
|
||||
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_addsNewProfiles() {
|
||||
LocalBluetoothProfile profile1 = mock(LocalBluetoothProfile.class);
|
||||
when(profile1.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile1));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
|
||||
LocalBluetoothProfile profile2 = mock(LocalBluetoothProfile.class);
|
||||
when(profile2.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Arrays.asList(profile1, profile2));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(1);
|
||||
assertThat(profilePreference.getProfile()).isEqualTo(profile2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_removesRemovedProfiles() {
|
||||
LocalBluetoothProfile profile1 = mock(LocalBluetoothProfile.class);
|
||||
when(profile1.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
LocalBluetoothProfile profile2 = mock(LocalBluetoothProfile.class);
|
||||
when(profile2.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Arrays.asList(profile1, profile2));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
|
||||
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile2));
|
||||
when(mBondedCachedDevice.getRemovedProfiles())
|
||||
.thenReturn(Collections.singletonList(profile1));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(profilePreference.getProfile()).isEqualTo(profile2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_profiles_showsPreference() {
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_noProfiles_hidesPreference() {
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.emptyList());
|
||||
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileChecked_setsProfilePreferred() {
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
profilePreference.refreshUi();
|
||||
|
||||
assertThat(profilePreference.isChecked()).isFalse();
|
||||
profilePreference.performClick();
|
||||
|
||||
verify(profile).setEnabled(mBondedDevice, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileChecked_connectsToProfile() {
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
profilePreference.refreshUi();
|
||||
|
||||
assertThat(profilePreference.isChecked()).isFalse();
|
||||
profilePreference.performClick();
|
||||
|
||||
verify(profile).setEnabled(mBondedDevice, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileUnchecked_setsProfileNotPreferred() {
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(profile.isEnabled(mBondedDevice)).thenReturn(true);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
profilePreference.refreshUi();
|
||||
|
||||
assertThat(profilePreference.isChecked()).isTrue();
|
||||
profilePreference.performClick();
|
||||
|
||||
verify(profile).setEnabled(mBondedDevice, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileUnchecked_disconnectsFromProfile() {
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(profile.isEnabled(mBondedDevice)).thenReturn(true);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
profilePreference.refreshUi();
|
||||
|
||||
assertThat(profilePreference.isChecked()).isTrue();
|
||||
profilePreference.performClick();
|
||||
|
||||
verify(profile).setEnabled(mBondedDevice, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileDisabled_showsToast() {
|
||||
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH))
|
||||
.thenReturn(true);
|
||||
when(mBondedCachedDevice.isBusy()).thenReturn(true);
|
||||
LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
|
||||
when(profile.getNameResource(mBondedDevice)).thenReturn(R.string.bt_profile_name);
|
||||
when(profile.isEnabled(mBondedDevice)).thenReturn(true);
|
||||
when(mBondedCachedDevice.getProfiles()).thenReturn(Collections.singletonList(profile));
|
||||
mPreferenceController.refreshUi();
|
||||
|
||||
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(
|
||||
true, CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP, 0).build();
|
||||
mPreferenceController.onUxRestrictionsChanged(restrictions);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
BluetoothDeviceProfilePreference profilePreference =
|
||||
(BluetoothDeviceProfilePreference) mPreferenceGroup.getPreference(0);
|
||||
profilePreference.refreshUi();
|
||||
profilePreference.performClick();
|
||||
|
||||
String toastText = mContext.getResources().getString(R.string.action_unavailable);
|
||||
|
||||
ExtendedMockito.verify(() -> Toast.makeText(any(), eq(toastText), anyInt()));
|
||||
verify(mMockToast).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.testutils.BaseCarSettingsTestActivity;
|
||||
import com.android.car.ui.toolbar.ToolbarController;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
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.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothPairingSelectionFragmentTest {
|
||||
private BluetoothPairingSelectionFragment mFragment;
|
||||
private BaseCarSettingsTestActivity mActivity;
|
||||
private FragmentManager mFragmentManager;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private LocalBluetoothManager mMockManager;
|
||||
@Mock
|
||||
private BluetoothEventManager mMockEventManager;
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<BaseCarSettingsTestActivity> mActivityTestRule =
|
||||
new ActivityTestRule<>(BaseCarSettingsTestActivity.class);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Throwable {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager();
|
||||
|
||||
mSession = ExtendedMockito.mockitoSession().mockStatic(
|
||||
BluetoothUtils.class, withSettings().lenient()).startMocking();
|
||||
when(BluetoothUtils.getLocalBtManager(any())).thenReturn(
|
||||
mMockManager);
|
||||
when(mMockManager.getEventManager()).thenReturn(mMockEventManager);
|
||||
CachedBluetoothDeviceManager cbdm = mock(CachedBluetoothDeviceManager.class);
|
||||
when(mMockManager.getCachedDeviceManager()).thenReturn(cbdm);
|
||||
setUpFragment();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_setsBluetoothManagerForegroundActivity() {
|
||||
verify(mMockManager).setForegroundActivity(mFragment.requireActivity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_registersEventListener() {
|
||||
verify(mMockEventManager).registerCallback(mFragment.mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_showsProgressBar() {
|
||||
ToolbarController toolbar = mActivity.getToolbar();
|
||||
|
||||
assertThat(toolbar.getProgressBar().isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_clearsBluetoothManagerForegroundActivity() throws Throwable {
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.onStop();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockManager).setForegroundActivity(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_unregistersEventListener() throws Throwable {
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.onStop();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockEventManager).registerCallback(mFragment.mCallback);
|
||||
verify(mMockEventManager).unregisterCallback(mFragment.mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_hidesProgressBar() throws Throwable {
|
||||
ToolbarController toolbar = mActivity.getToolbar();
|
||||
toolbar.getProgressBar().setVisible(true);
|
||||
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.onStop();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(toolbar.getProgressBar().isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_deviceBonded_goesBack() throws Throwable {
|
||||
verify(mMockEventManager).registerCallback(mFragment.mCallback);
|
||||
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.mCallback.onDeviceBondStateChanged(mock(CachedBluetoothDevice.class),
|
||||
BluetoothDevice.BOND_BONDED);
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(mActivity.getOnBackPressedFlag()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothDisabled_goesBack() throws Throwable {
|
||||
verify(mMockEventManager).registerCallback(mFragment.mCallback);
|
||||
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragment.mCallback.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
assertThat(mActivity.getOnBackPressedFlag()).isTrue();
|
||||
}
|
||||
|
||||
private void setUpFragment() throws Throwable {
|
||||
String bluetoothPairingSelectionFragmentTag = "bluetooth_pairing_selection_fragment";
|
||||
mActivityTestRule.runOnUiThread(() -> {
|
||||
mFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_container, new BluetoothPairingSelectionFragment(),
|
||||
bluetoothPairingSelectionFragmentTag)
|
||||
.commitNow();
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
mFragment = (BluetoothPairingSelectionFragment)
|
||||
mFragmentManager.findFragmentByTag(bluetoothPairingSelectionFragmentTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.android.car.settings.bluetooth.BluetoothRequestPermissionActivity.DEFAULT_DISCOVERABLE_TIMEOUT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
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 static org.mockito.Mockito.withSettings;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
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.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothRequestPermissionActivityTest {
|
||||
private static final String PACKAGE_NAME = "pkg.test";
|
||||
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private TestBluetoothRequestPermissionActivity mActivity;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<TestBluetoothRequestPermissionActivity> mActivityTestRule =
|
||||
new ActivityTestRule<>(TestBluetoothRequestPermissionActivity.class, false, false);
|
||||
@Mock
|
||||
private LocalBluetoothManager mMockLocalBluetoothManager;
|
||||
@Mock
|
||||
private LocalBluetoothAdapter mMockLocalBluetoothAdapter;
|
||||
@Mock
|
||||
private PackageManager mMockPackageManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
// Fields that need to be mocked in activity's onCreate(). Workaround since ActivityTestRule
|
||||
// doesn't create the activity instance or context until launched, so the fields can't be
|
||||
// mocked normally.
|
||||
TestBluetoothRequestPermissionActivity.PACKAGE_MANAGER = mMockPackageManager;
|
||||
TestBluetoothRequestPermissionActivity.CALLING_PACKAGE = PACKAGE_NAME;
|
||||
|
||||
when(mMockPackageManager.getApplicationInfo(PACKAGE_NAME, 0))
|
||||
.thenReturn(new ApplicationInfo());
|
||||
|
||||
mSession = ExtendedMockito.mockitoSession().mockStatic(
|
||||
LocalBluetoothManager.class, withSettings().lenient()).startMocking();
|
||||
ExtendedMockito.when(LocalBluetoothManager.getInstance(any(), any()))
|
||||
.thenReturn(mMockLocalBluetoothManager);
|
||||
when(mMockLocalBluetoothManager.getBluetoothAdapter())
|
||||
.thenReturn(mMockLocalBluetoothAdapter);
|
||||
when(mMockLocalBluetoothAdapter.setScanMode(
|
||||
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, DEFAULT_DISCOVERABLE_TIMEOUT))
|
||||
.thenReturn(false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDisableIntent_hasDisableRequestType() {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getRequestType()).isEqualTo(
|
||||
BluetoothRequestPermissionActivity.REQUEST_DISABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_hasDiscoverableRequestType() {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getRequestType()).isEqualTo(
|
||||
BluetoothRequestPermissionActivity.REQUEST_ENABLE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_noTimeoutSpecified_hasDefaultTimeout() {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getTimeout()).isEqualTo(
|
||||
DEFAULT_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_timeoutSpecified_hasTimeout() {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
|
||||
BluetoothRequestPermissionActivity.MAX_DISCOVERABLE_TIMEOUT);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getTimeout()).isEqualTo(
|
||||
BluetoothRequestPermissionActivity.MAX_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_bypassforSetup_startsDiscoverableScan() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = createSetupWizardIntent();
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
|
||||
verify(mMockLocalBluetoothAdapter).setScanMode(
|
||||
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, DEFAULT_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_bypassforSetup_turningOn_noDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_TURNING_ON);
|
||||
Intent intent = createSetupWizardIntent();
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_bypassforSetup_turningOn_receiverRegistered() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_TURNING_ON);
|
||||
Intent intent = createSetupWizardIntent();
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentReceiver()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_bypassforSetup_turningOn_enableDiscovery() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_TURNING_ON);
|
||||
|
||||
Intent intent = createSetupWizardIntent();
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
// Simulate bluetooth callback from STATE_TURNING_ON to STATE_ON
|
||||
Intent stateChangedIntent = new Intent();
|
||||
stateChangedIntent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
|
||||
mActivity.getCurrentReceiver().onReceive(mContext, stateChangedIntent);
|
||||
|
||||
verify(mMockLocalBluetoothAdapter).setScanMode(
|
||||
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, DEFAULT_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestDiscoverableIntent_bypassforGeneric_noScanModeChange() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
intent.putExtra(BluetoothRequestPermissionActivity.EXTRA_BYPASS_CONFIRM_DIALOG, true);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
verify(mMockLocalBluetoothAdapter, never()).setScanMode(
|
||||
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, DEFAULT_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_requestEnableIntent_hasEnableRequestType() {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getRequestType()).isEqualTo(
|
||||
BluetoothRequestPermissionActivity.REQUEST_ENABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOff_requestDisableIntent_noDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOn_requestDisableIntent_startsDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNotNull();
|
||||
assertThat(mActivity.getCurrentDialog().isShowing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOff_requestDiscoverableIntent_startsDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNotNull();
|
||||
assertThat(mActivity.getCurrentDialog().isShowing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOn_requestDiscoverableIntent_startsDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNotNull();
|
||||
assertThat(mActivity.getCurrentDialog().isShowing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOff_requestEnableIntent_startsDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNotNull();
|
||||
assertThat(mActivity.getCurrentDialog().isShowing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_bluetoothOn_requestEnableIntent_noDialog() {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
assertThat(mActivity.getCurrentDialog()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPositiveClick_disableDialog_disables() throws Throwable {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
Button button = mActivity.getCurrentDialog().getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
mActivityTestRule.runOnUiThread(button::performClick);
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockLocalBluetoothAdapter).disable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPositiveClick_discoverableDialog_scanModeSet() throws Throwable {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
Button button = mActivity.getCurrentDialog().getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
mActivityTestRule.runOnUiThread(button::performClick);
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockLocalBluetoothAdapter).setScanMode(
|
||||
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, DEFAULT_DISCOVERABLE_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPositiveClick_enableDialog_enables() throws Throwable {
|
||||
when(mMockLocalBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
mActivityTestRule.launchActivity(intent);
|
||||
mActivity = mActivityTestRule.getActivity();
|
||||
|
||||
Button button = mActivity.getCurrentDialog().getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
mActivityTestRule.runOnUiThread(button::performClick);
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mMockLocalBluetoothAdapter).enable();
|
||||
}
|
||||
|
||||
private Intent createSetupWizardIntent() {
|
||||
ResolveInfo resolveInfo = new ResolveInfo();
|
||||
resolveInfo.activityInfo = new ActivityInfo();
|
||||
resolveInfo.activityInfo.packageName = PACKAGE_NAME;
|
||||
|
||||
when(mMockPackageManager.queryIntentActivities(any(), anyInt()))
|
||||
.thenReturn(Collections.singletonList(resolveInfo));
|
||||
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
intent.setComponent(new ComponentName(mContext,
|
||||
TestBluetoothRequestPermissionActivity.class));
|
||||
intent.putExtra(BluetoothRequestPermissionActivity.EXTRA_BYPASS_CONFIRM_DIALOG, true);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
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 static org.mockito.Mockito.withSettings;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothScanningDevicesGroupPreferenceControllerTest {
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private TestBluetoothScanningDevicesGroupPreferenceController mController;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private LocalBluetoothManager mMockManager;
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock
|
||||
private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
when(mBluetoothAdapter.startDiscovery()).then(invocation -> {
|
||||
when(mBluetoothAdapter.isDiscovering()).thenReturn(true);
|
||||
return true;
|
||||
});
|
||||
when(mBluetoothAdapter.cancelDiscovery()).then(invocation -> {
|
||||
when(mBluetoothAdapter.isDiscovering()).thenReturn(false);
|
||||
return true;
|
||||
});
|
||||
BluetoothManager bluetoothManager = mock(BluetoothManager.class);
|
||||
when(bluetoothManager.getAdapter()).thenReturn(mBluetoothAdapter);
|
||||
when(mContext.getSystemService(BluetoothManager.class)).thenReturn(bluetoothManager);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mSession = ExtendedMockito.mockitoSession().mockStatic(
|
||||
BluetoothUtils.class, withSettings().lenient()).startMocking();
|
||||
when(BluetoothUtils.getLocalBtManager(any())).thenReturn(
|
||||
mMockManager);
|
||||
when(BluetoothUtils.shouldEnableBTScanning(eq(mContext), any())).thenReturn(true);
|
||||
when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mCachedDevice.getDevice()).thenReturn(mDevice);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||
Collections.singletonList(mCachedDevice));
|
||||
when(mMockManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mMockManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
|
||||
mController = new TestBluetoothScanningDevicesGroupPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController,
|
||||
mCarUxRestrictions);
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
PreferenceControllerTestUtil.assignPreference(mController, mPreferenceGroup);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disallowConfigBluetooth_doesNotStartScanning() {
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)).thenReturn(true);
|
||||
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
verify(mBluetoothAdapter, never()).startDiscovery();
|
||||
// User can't scan, but they can still see known devices.
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScanningStateChanged_scanningEnabled_receiveStopped_restartsScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
|
||||
Mockito.clearInvocations(mBluetoothAdapter);
|
||||
mBluetoothAdapter.cancelDiscovery();
|
||||
mController.onScanningStateChanged(/* started= */ false);
|
||||
// start discovery should be called a second time after the state change
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScanningStateChanged_scanningDisabled_receiveStopped_doesNothing() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
// Set a device bonding to disable scanning.
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
mController.refreshUi();
|
||||
verify(mBluetoothAdapter).cancelDiscovery();
|
||||
|
||||
Mockito.clearInvocations(mBluetoothAdapter);
|
||||
mController.onScanningStateChanged(/* started= */ false);
|
||||
verify(mBluetoothAdapter, never()).startDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_refreshesUi() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
|
||||
// Change state to bonding to cancel scanning on refresh.
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
mController.onDeviceBondStateChanged(mCachedDevice, BluetoothDevice.BOND_BONDING);
|
||||
|
||||
verify(mBluetoothAdapter).cancelDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_callsInternal() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
assertThat(mController.getLastClickedDevice()).isEquivalentAccordingToCompareTo(
|
||||
devicePreference.getCachedDevice());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_cancelsScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mBluetoothAdapter).cancelDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_noDeviceBonding_startsScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_noDeviceBonding_enablesGroup() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_noDeviceBonding_setsScanModeConnectableDiscoverable() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
verify(mBluetoothAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_notValidCallingPackage_doesNotSetScanMode() {
|
||||
when(BluetoothUtils.shouldEnableBTScanning(eq(mContext), any())).thenReturn(false);
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
verify(mBluetoothAdapter, never())
|
||||
.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_deviceBonding_stopsScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
verify(mBluetoothAdapter).cancelDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_deviceBonding_disablesGroup() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
assertThat(mPreferenceGroup.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_deviceBonding_setsScanModeConnectable() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
|
||||
|
||||
mController.refreshUi();
|
||||
|
||||
verify(mBluetoothAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_stopsScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
|
||||
mController.onStop(mLifecycleOwner);
|
||||
|
||||
verify(mBluetoothAdapter).cancelDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_clearsNonBondedDevices() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
|
||||
verify(mCachedDeviceManager).clearNonBondedDevices();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_clearsGroup() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isGreaterThan(0);
|
||||
|
||||
mController.onStop(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_setsScanModeConnectable() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
Mockito.clearInvocations(mBluetoothAdapter);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
|
||||
verify(mBluetoothAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoverableScanModeTimeout_controllerStarted_resetsDiscoverableScanMode() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
when(mBluetoothAdapter.getScanMode()).thenReturn(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
|
||||
mContext.sendBroadcast(new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
|
||||
|
||||
verify(mBluetoothAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoverableScanModeTimeout_controllerStopped_doesNotResetDiscoverableScanMode() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
|
||||
Mockito.clearInvocations(mBluetoothAdapter);
|
||||
when(mBluetoothAdapter.getScanMode()).thenReturn(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
|
||||
mContext.sendBroadcast(new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
|
||||
|
||||
verify(mBluetoothAdapter, never())
|
||||
.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
private static final class TestBluetoothScanningDevicesGroupPreferenceController extends
|
||||
BluetoothScanningDevicesGroupPreferenceController {
|
||||
|
||||
private CachedBluetoothDevice mLastClickedDevice;
|
||||
|
||||
TestBluetoothScanningDevicesGroupPreferenceController(Context context,
|
||||
String preferenceKey,
|
||||
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
|
||||
super(context, preferenceKey, fragmentController, uxRestrictions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceClickedInternal(CachedBluetoothDevice cachedDevice) {
|
||||
mLastClickedDevice = cachedDevice;
|
||||
}
|
||||
|
||||
CachedBluetoothDevice getLastClickedDevice() {
|
||||
return mLastClickedDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BluetoothDeviceFilter.Filter getDeviceFilter() {
|
||||
return BluetoothDeviceFilter.ALL_FILTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.car.settings.bluetooth;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_BLUETOOTH;
|
||||
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
|
||||
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.android.car.settings.common.PreferenceController.DISABLED_FOR_PROFILE;
|
||||
import static com.android.car.settings.common.PreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.common.ColoredSwitchPreference;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.EnterpriseTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothStateSwitchPreferenceControllerTest {
|
||||
private static final String TEST_RESTRICTION =
|
||||
android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private SwitchPreference mSwitchPreference;
|
||||
private BluetoothStateSwitchPreferenceController mPreferenceController;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mLocalBluetoothManager = LocalBluetoothManager.getInstance(mContext, /* onInitCallback= */
|
||||
null);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
mSwitchPreference = new ColoredSwitchPreference(mContext);
|
||||
mPreferenceController = new BluetoothStateSwitchPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mSwitchPreference);
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_setsBluetoothManagerForegroundActivity() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mLocalBluetoothManager.getForegroundActivity()).isEqualTo(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_clearsBluetoothManagerForegroundActivity() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mPreferenceController.onStop(mLifecycleOwner);
|
||||
|
||||
assertThat(mLocalBluetoothManager.getForegroundActivity()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_initializesSwitchState() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isEqualTo(
|
||||
BluetoothAdapter.getDefaultAdapter().isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchClicked_disabled_checksAndDisablesSwitch() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mSwitchPreference.setChecked(false);
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ false);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_bluetoothFeatureDisabled() {
|
||||
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(false);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_noRestrictions() {
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_restrictedByUm() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneWrite() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("write");
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneRead() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("read");
|
||||
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneHidden() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("hidden");
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_disableSwitchPreference() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mSwitchPreference.setEnabled(true);
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_showsDisabledByAdminDialog() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertShowingDisabledByAdminDialog();
|
||||
}
|
||||
|
||||
private void assertShowingDisabledByAdminDialog() {
|
||||
verify(mFragmentController).showDialog(any(), eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchClicked_enabled_unchecksAndDisablesSwitch() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
mSwitchPreference.setChecked(true);
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_turningOn_setsSwitchChecked() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_TURNING_ON);
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_turningOn_setsSwitchDisabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_TURNING_ON);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_on_setsSwitchChecked() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_on_setsSwitchEnabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_turningOff_setsSwitchUnchecked() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_TURNING_OFF);
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_turningOff_setsSwitchDisabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_TURNING_OFF);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_off_setsSwitchUnchecked() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_off_setsSwitchEnabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_on_userRestricted_setsSwitchDisabled() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_BLUETOOTH)).thenReturn(true);
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateChanged_off_userRestricted_setsSwitchDisabled() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_BLUETOOTH)).thenReturn(true);
|
||||
|
||||
mPreferenceController.handleStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPolicyChanged_enabled_setsSwitchEnabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mSwitchPreference.setEnabled(false);
|
||||
|
||||
mPreferenceController.mPowerPolicyListener.getPolicyChangeHandler()
|
||||
.handlePolicyChange(/* isOn= */ true);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPolicyChanged_disabled_setsSwitchDisabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mSwitchPreference.setEnabled(true);
|
||||
|
||||
mPreferenceController.mPowerPolicyListener.getPolicyChangeHandler()
|
||||
.handlePolicyChange(/* isOn= */ false);
|
||||
|
||||
assertThat(mSwitchPreference.isEnabled()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
import static com.android.car.settings.common.PreferenceController.DISABLED_FOR_PROFILE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.LogicalPreferenceGroup;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.testutils.BluetoothTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BluetoothUnbondedDevicesPreferenceControllerTest {
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private BluetoothUnbondedDevicesPreferenceController mController;
|
||||
private int[] mUnbondedDeviceFilter;
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mUnbondedCachedDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mUnbondedDevice;
|
||||
@Mock
|
||||
private BluetoothClass mBluetoothClass;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock
|
||||
private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
mUnbondedDeviceFilter = new int[]{};
|
||||
Resources resources = spy(mContext.getResources());
|
||||
when(mContext.getResources()).thenReturn(resources);
|
||||
when(resources.getIntArray(R.array.config_unbonded_device_filter_allowlist))
|
||||
.thenReturn(mUnbondedDeviceFilter);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
|
||||
// Ensure bluetooth is available and enabled.
|
||||
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
|
||||
BluetoothTestUtils.setBluetoothState(mContext, /* enable= */ true);
|
||||
|
||||
when(mUnbondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mUnbondedCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
when(mUnbondedCachedDevice.getDevice()).thenReturn(mUnbondedDevice);
|
||||
when(mBluetoothClass.getMajorDeviceClass()).thenReturn(BluetoothClass.Device.Major.PHONE);
|
||||
when(mUnbondedDevice.getBluetoothClass()).thenReturn(mBluetoothClass);
|
||||
BluetoothDevice bondedDevice = mock(BluetoothDevice.class);
|
||||
when(bondedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothAdapter.getBondedDevices()).thenReturn(Collections.singleton(bondedDevice));
|
||||
BluetoothManager bluetoothManager = mock(BluetoothManager.class);
|
||||
when(bluetoothManager.getAdapter()).thenReturn(mBluetoothAdapter);
|
||||
when(mContext.getSystemService(BluetoothManager.class)).thenReturn(bluetoothManager);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
CachedBluetoothDevice bondedCachedDevice = mock(CachedBluetoothDevice.class);
|
||||
when(bondedCachedDevice.getDevice()).thenReturn(bondedDevice);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||
Arrays.asList(mUnbondedCachedDevice, bondedCachedDevice));
|
||||
mSession = ExtendedMockito.mockitoSession().mockStatic(
|
||||
BluetoothUtils.class, withSettings().lenient()).startMocking();
|
||||
when(BluetoothUtils.getLocalBtManager(any())).thenReturn(
|
||||
mLocalBluetoothManager);
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
|
||||
mController = new BluetoothUnbondedDevicesPreferenceController(mContext,
|
||||
/* preferenceKey= */ "key", mFragmentController,
|
||||
mCarUxRestrictions);
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
|
||||
screen.addPreference(mPreferenceGroup);
|
||||
PreferenceControllerTestUtil.assignPreference(mController, mPreferenceGroup);
|
||||
}
|
||||
|
||||
@After
|
||||
@UiThreadTest
|
||||
public void tearDown() {
|
||||
if (mSession != null) {
|
||||
mSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showsUnbondedDevices() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(devicePreference.getCachedDevice()).isEqualTo(mUnbondedCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configUnbondedDeviceFilterIncludesPhones_showsUnbondedPhones() {
|
||||
mUnbondedDeviceFilter = new int[] {BluetoothClass.Device.Major.PHONE};
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
assertThat(devicePreference.getCachedDevice()).isEqualTo(mUnbondedCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_startsPairing() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mUnbondedCachedDevice).startPairing();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_pairingStartFails_resumesScanning() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
when(mUnbondedCachedDevice.startPairing()).thenReturn(false);
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
|
||||
Mockito.clearInvocations(mBluetoothAdapter);
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mBluetoothAdapter).startDiscovery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_requestsPhonebookAccess() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
when(mUnbondedCachedDevice.startPairing()).thenReturn(true);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mUnbondedDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceClicked_requestsMessageAccess() {
|
||||
mController.onCreate(mLifecycleOwner);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
when(mUnbondedCachedDevice.startPairing()).thenReturn(true);
|
||||
BluetoothDevicePreference devicePreference =
|
||||
(BluetoothDevicePreference) mPreferenceGroup.getPreference(0);
|
||||
|
||||
devicePreference.performClick();
|
||||
|
||||
verify(mUnbondedDevice).setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_disallowConfigBluetooth_disabledForUser() {
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_disallowConfigBluetooth_disabledForUser_zoneWrite() {
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)).thenReturn(true);
|
||||
mController.setAvailabilityStatusForZone("write");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
|
||||
DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_disallowConfigBluetooth_disabledForUser_zoneRead() {
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)).thenReturn(true);
|
||||
mController.setAvailabilityStatusForZone("read");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
|
||||
DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_disallowConfigBluetooth_disabledForUser_zoneHidden() {
|
||||
when(mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)).thenReturn(true);
|
||||
mController.setAvailabilityStatusForZone("hidden");
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
|
||||
DISABLED_FOR_PROFILE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.car.settings.bluetooth;
|
||||
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
|
||||
import static com.android.car.settings.common.PreferenceController.DISABLED_FOR_PROFILE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.car.settings.testutils.EnterpriseTestUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class BluetoothUtilsTest {
|
||||
|
||||
private static final String TEST_RESTRICTION =
|
||||
android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
private static final String SYSTEM_UI_PACKAGE_NAME = "com.package.systemui";
|
||||
private static final String SYSTEM_UI_COMPONENT_NAME = "com.package.systemui/testclass";
|
||||
private static final String ALLOWED_PACKAGE_NAME = "com.allowed.package";
|
||||
private static final String DISALLOWED_PACKAGE_NAME = "not.real.package";
|
||||
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
|
||||
@Mock
|
||||
private UserManager mMockUserManager;
|
||||
@Mock
|
||||
private Resources mMockResources;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
|
||||
when(mContext.getResources()).thenReturn(mMockResources);
|
||||
when(mMockResources.getString(anyInt())).thenReturn(SYSTEM_UI_COMPONENT_NAME);
|
||||
|
||||
String[] allowedPackages = new String[1];
|
||||
allowedPackages[0] = ALLOWED_PACKAGE_NAME;
|
||||
when(mMockResources.getStringArray(anyInt())).thenReturn(allowedPackages);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatusRestricted_unrestricted_available() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, false);
|
||||
|
||||
assertThat(BluetoothUtils.getAvailabilityStatusRestricted(mContext)).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatusRestricted_restrictedByUm_disabled() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
assertThat(BluetoothUtils.getAvailabilityStatusRestricted(mContext))
|
||||
.isEqualTo(DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatusRestricted_restrictedByDpm_viewing() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
assertThat(BluetoothUtils.getAvailabilityStatusRestricted(mContext))
|
||||
.isEqualTo(AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatusRestricted_restrictedByBothUmAndDpm_disabled() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByUm(mMockUserManager, TEST_RESTRICTION, true);
|
||||
|
||||
assertThat(BluetoothUtils.getAvailabilityStatusRestricted(mContext))
|
||||
.isEqualTo(DISABLED_FOR_PROFILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSystemCallingPackage_shouldEnableBluetoothScanning() {
|
||||
String settingsPackage = mContext.getPackageName();
|
||||
|
||||
assertThat(BluetoothUtils.shouldEnableBTScanning(mContext, settingsPackage))
|
||||
.isEqualTo(true);
|
||||
assertThat(BluetoothUtils.shouldEnableBTScanning(mContext, SYSTEM_UI_PACKAGE_NAME))
|
||||
.isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAllowedCallingPackage_shouldEnableBluetoothScanning() {
|
||||
assertThat(BluetoothUtils.shouldEnableBTScanning(mContext, ALLOWED_PACKAGE_NAME))
|
||||
.isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotAllowedCallingPackage_shouldNotEnableBluetoothScanning() {
|
||||
assertThat(BluetoothUtils.shouldEnableBTScanning(mContext, DISALLOWED_PACKAGE_NAME))
|
||||
.isEqualTo(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
|
||||
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG;
|
||||
|
||||
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.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
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.car.drivingstate.CarUxRestrictions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.car.settings.R;
|
||||
import com.android.car.settings.common.ColoredSwitchPreference;
|
||||
import com.android.car.settings.common.FragmentController;
|
||||
import com.android.car.settings.common.PreferenceControllerTestUtil;
|
||||
import com.android.car.settings.common.Settings;
|
||||
import com.android.car.settings.testutils.EnterpriseTestUtils;
|
||||
import com.android.car.settings.testutils.TestLifecycleOwner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public final class PairNewDevicePreferenceControllerUnitTest {
|
||||
private static final String TEST_RESTRICTION =
|
||||
android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private SwitchPreference mSwitchPreference;
|
||||
private PairNewDevicePreferenceController mPreferenceController;
|
||||
private CarUxRestrictions mCarUxRestrictions;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
@Mock
|
||||
private FragmentController mFragmentController;
|
||||
|
||||
@Mock
|
||||
private PackageManager mMockPm;
|
||||
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mLifecycleOwner = new TestLifecycleOwner();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
|
||||
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
|
||||
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
|
||||
mPreferenceController = new PairNewDevicePreferenceController(mContext, /* preferenceKey= */
|
||||
"key", mFragmentController, mCarUxRestrictions);
|
||||
mSwitchPreference = new ColoredSwitchPreference(mContext);
|
||||
mSwitchPreference.setFragment(FragmentController.class.getCanonicalName());
|
||||
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mSwitchPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneWrite() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("write");
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneRead() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("read");
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_availabilityIsAvailableForViewing_zoneHidden() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.setAvailabilityStatusForZone("hidden");
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
PreferenceControllerTestUtil.assertAvailability(
|
||||
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedByDpm_showsDisabledByAdminDialog() {
|
||||
EnterpriseTestUtils.mockUserRestrictionSetByDpm(mUserManager, TEST_RESTRICTION, true);
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
assertShowingDisabledByAdminDialog();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_triggersCustomPairingFlow_whenSystemApplicationIsFound() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mMockPm);
|
||||
|
||||
Intent intent = new Intent(Settings.ACTION_PAIR_DEVICE_SETTINGS);
|
||||
mSwitchPreference.setIntent(intent);
|
||||
|
||||
String packageName = "some.test.package";
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getBoolean(
|
||||
R.bool.config_use_custom_pair_device_flow)).thenReturn(true);
|
||||
when(mMockPm.queryIntentActivities(eq(intent), anyInt())).thenReturn(
|
||||
Collections.singletonList(createSystemResolveInfo(packageName)));
|
||||
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
|
||||
assertThat(mSwitchPreference.getOnPreferenceClickListener().onPreferenceClick(
|
||||
mSwitchPreference)).isTrue();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).startActivity(captor.capture());
|
||||
|
||||
Intent capturedIntent = captor.getValue();
|
||||
assertThat(capturedIntent.getAction()).isEqualTo(Settings.ACTION_PAIR_DEVICE_SETTINGS);
|
||||
assertThat(capturedIntent.getPackage()).isEqualTo(packageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_triggersDefaultPairingFlow_whenNoMatchingApplicationsFound() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_PAIR_DEVICE_SETTINGS);
|
||||
mSwitchPreference.setIntent(intent);
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getBoolean(
|
||||
R.bool.config_use_custom_pair_device_flow)).thenReturn(true);
|
||||
when(mContext.getPackageManager()).thenReturn(mMockPm);
|
||||
when(mMockPm.queryIntentActivities(eq(intent), anyInt())).thenReturn(
|
||||
Collections.emptyList());
|
||||
|
||||
assertThat(mSwitchPreference.getOnPreferenceClickListener().onPreferenceClick(
|
||||
mSwitchPreference)).isFalse();
|
||||
|
||||
verify(mContext, never()).startActivity(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_triggersDefaultPairingFlow_whenNonSystemApplicationIsFound() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mMockPm);
|
||||
|
||||
Intent intent = new Intent(Settings.ACTION_PAIR_DEVICE_SETTINGS);
|
||||
mSwitchPreference.setIntent(intent);
|
||||
|
||||
String packageName = "some.test.package";
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getBoolean(
|
||||
R.bool.config_use_custom_pair_device_flow)).thenReturn(true);
|
||||
when(mMockPm.queryIntentActivities(eq(intent), anyInt())).thenReturn(
|
||||
Collections.singletonList(createNonSystemResolveInfo(packageName)));
|
||||
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
|
||||
assertThat(mSwitchPreference.getOnPreferenceClickListener().onPreferenceClick(
|
||||
mSwitchPreference)).isFalse();
|
||||
|
||||
verify(mContext, never()).startActivity(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceClicked_triggersDefaultPairingFlow_whenCustomPairingFlowIsDisabled() {
|
||||
mPreferenceController.onCreate(mLifecycleOwner);
|
||||
mPreferenceController.onStart(mLifecycleOwner);
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getBoolean(
|
||||
R.bool.config_use_custom_pair_device_flow)).thenReturn(false);
|
||||
|
||||
assertThat(mSwitchPreference.getOnPreferenceClickListener().onPreferenceClick(
|
||||
mSwitchPreference)).isFalse();
|
||||
}
|
||||
|
||||
private void assertShowingDisabledByAdminDialog() {
|
||||
verify(mFragmentController).showDialog(any(), eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
|
||||
}
|
||||
|
||||
private ResolveInfo createSystemResolveInfo(String packageName) {
|
||||
ResolveInfo resolveInfo = createNonSystemResolveInfo(packageName);
|
||||
resolveInfo.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
return resolveInfo;
|
||||
}
|
||||
|
||||
private ResolveInfo createNonSystemResolveInfo(String packageName) {
|
||||
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||
|
||||
ActivityInfo activityInfo = new ActivityInfo();
|
||||
activityInfo.applicationInfo = applicationInfo;
|
||||
|
||||
ResolveInfo resolveInfo = new ResolveInfo();
|
||||
resolveInfo.activityInfo = activityInfo;
|
||||
resolveInfo.activityInfo.packageName = packageName;
|
||||
|
||||
return resolveInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.car.settings.bluetooth;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
public class TestBluetoothRequestPermissionActivity extends BluetoothRequestPermissionActivity {
|
||||
// Fields that need to be mocked in onCreate()
|
||||
public static PackageManager PACKAGE_MANAGER;
|
||||
public static String CALLING_PACKAGE;
|
||||
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return PACKAGE_MANAGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCallingPackage() {
|
||||
return CALLING_PACKAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLaunchedFromPackage() {
|
||||
return CALLING_PACKAGE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user