Merge 10952656
Merged-In: Ib02ae9caef06a46938947806dac8aabb1fa12d94 Change-Id: Ib1f728fef6241ddd7a2ce1522093f4a62a4a9d81
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.appcompat;
|
||||
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
|
||||
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE;
|
||||
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE;
|
||||
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.platform.test.rule.DeviceTypeRule;
|
||||
import android.platform.test.rule.FoldableOnly;
|
||||
import android.platform.test.rule.LargeScreenOnly;
|
||||
import android.platform.test.rule.TabletOnly;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* To run this test: atest SettingsUnitTests:UserAspectRatioManagerTest
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeScreenOnly
|
||||
public class UserAspectRatioManagerTest {
|
||||
|
||||
private Context mContext;
|
||||
private Resources mResources;
|
||||
private UserAspectRatioManager mUtils;
|
||||
private String mOriginalSettingsFlag;
|
||||
private String mOriginalFullscreenFlag;
|
||||
private String mPackageName = "com.test.mypackage";
|
||||
private LauncherApps mLauncherApps;
|
||||
private List<LauncherActivityInfo> mLauncherActivities;
|
||||
|
||||
@Rule
|
||||
public TestRule mDeviceTypeRule = new DeviceTypeRule();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(mContext.getResources());
|
||||
mLauncherApps = mock(LauncherApps.class);
|
||||
mLauncherActivities = mock(List.class);
|
||||
mUtils = new UserAspectRatioManager(mContext) {
|
||||
@Override
|
||||
LauncherApps getLauncherApps() {
|
||||
return mLauncherApps;
|
||||
}
|
||||
};
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
doReturn(mLauncherActivities).when(mLauncherApps).getActivityList(anyString(), any());
|
||||
|
||||
mOriginalSettingsFlag = DeviceConfig.getProperty(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS);
|
||||
setAspectRatioSettingsBuildTimeFlagEnabled(true);
|
||||
setAspectRatioSettingsDeviceConfigEnabled("true" /* enabled */, false /* makeDefault */);
|
||||
|
||||
mOriginalFullscreenFlag = DeviceConfig.getProperty(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN);
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(true);
|
||||
setAspectRatioFullscreenDeviceConfigEnabled("true" /* enabled */, false /* makeDefault */);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
setAspectRatioSettingsDeviceConfigEnabled(mOriginalSettingsFlag, true /* makeDefault */);
|
||||
setAspectRatioFullscreenDeviceConfigEnabled(mOriginalFullscreenFlag,
|
||||
true /* makeDefault */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDisplayAspectRatioUi() {
|
||||
final ApplicationInfo canDisplay = new ApplicationInfo();
|
||||
canDisplay.packageName = "com.app.candisplay";
|
||||
|
||||
doReturn(false).when(mLauncherActivities).isEmpty();
|
||||
assertTrue(mUtils.canDisplayAspectRatioUi(canDisplay));
|
||||
|
||||
final ApplicationInfo noLauncherEntry = new ApplicationInfo();
|
||||
noLauncherEntry.packageName = "com.app.nolauncherentry";
|
||||
|
||||
doReturn(true).when(mLauncherActivities).isEmpty();
|
||||
assertFalse(mUtils.canDisplayAspectRatioUi(noLauncherEntry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDisplayAspectRatioUi_hasLauncher_propertyFalse_returnFalse()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, false);
|
||||
doReturn(true).when(mLauncherActivities).isEmpty();
|
||||
|
||||
final ApplicationInfo canDisplay = new ApplicationInfo();
|
||||
canDisplay.packageName = mPackageName;
|
||||
|
||||
assertFalse(mUtils.canDisplayAspectRatioUi(canDisplay));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDisplayAspectRatioUi_noLauncher_propertyTrue_returnFalse()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, true);
|
||||
doReturn(true).when(mLauncherActivities).isEmpty();
|
||||
|
||||
final ApplicationInfo noLauncherEntry = new ApplicationInfo();
|
||||
noLauncherEntry.packageName = mPackageName;
|
||||
|
||||
assertFalse(mUtils.canDisplayAspectRatioUi(noLauncherEntry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled() {
|
||||
assertTrue(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled_disabledBuildTimeFlag_returnFalse() {
|
||||
setAspectRatioSettingsBuildTimeFlagEnabled(false);
|
||||
assertFalse(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled_disabledRuntimeFlag_returnFalse() {
|
||||
setAspectRatioSettingsDeviceConfigEnabled("false" /* enabled */, false /* makeDefault */);
|
||||
assertFalse(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled() {
|
||||
assertTrue(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_settingsDisabled_returnFalse() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_disabledBuildTimeFlag_returnFalse() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_disabledRuntimeFlag_returnFalse() {
|
||||
setAspectRatioFullscreenDeviceConfigEnabled("false" /* enabled */, false /*makeDefault */);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_propertyFalse_returnsFalse()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, false);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_propertyTrue_configDisabled_returnsFalse()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, true);
|
||||
setAspectRatioFullscreenDeviceConfigEnabled("false" /* enabled */, false /*makeDefault */);
|
||||
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled(mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasAspectRatioOption_fullscreen() {
|
||||
assertTrue(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mPackageName));
|
||||
assertTrue(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
|
||||
mPackageName));
|
||||
|
||||
// Only fullscreen option should be disabled
|
||||
when(mUtils.isFullscreenOptionEnabled(mPackageName)).thenReturn(false);
|
||||
assertFalse(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mPackageName));
|
||||
assertTrue(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
|
||||
mPackageName));
|
||||
}
|
||||
|
||||
@Test
|
||||
@FoldableOnly
|
||||
public void testGetUserMinAspectRatioEntry_Foldable() {
|
||||
// R.string.user_aspect_ratio_app_default
|
||||
final String appDefault = ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_app_default");
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName))
|
||||
.isEqualTo(appDefault);
|
||||
// should always return default if value does not correspond to anything
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(-1, mPackageName))
|
||||
.isEqualTo(appDefault);
|
||||
// R.string.user_aspect_ratio_half_screen
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
|
||||
mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_half_screen"));
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_fullscreen"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TabletOnly
|
||||
public void testGetUserMinAspectRatioEntry_Tablet() {
|
||||
// R.string.user_aspect_ratio_app_default
|
||||
final String appDefault = ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_app_default");
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName))
|
||||
.isEqualTo(appDefault);
|
||||
// should always return default if value does not correspond to anything
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(-1, mPackageName))
|
||||
.isEqualTo(appDefault);
|
||||
// R.string.user_aspect_ratio_half_screen
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
|
||||
mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_half_screen"));
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_16_9, mPackageName))
|
||||
.isEqualTo(ResourcesUtils.getResourcesString(mContext, "user_aspect_ratio_16_9"));
|
||||
// R.string.user_aspect_ratio_fullscreen
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_fullscreen"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserMinAspectRatioEntry_fullscreenDisabled_shouldReturnDefault() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_app_default"));
|
||||
}
|
||||
|
||||
private void mockProperty(String propertyName, boolean value)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
PackageManager.Property prop = new PackageManager.Property(
|
||||
propertyName, value, mPackageName, "" /* className */);
|
||||
PackageManager pm = mock(PackageManager.class);
|
||||
when(mContext.getPackageManager()).thenReturn(pm);
|
||||
when(pm.getProperty(propertyName, mPackageName)).thenReturn(prop);
|
||||
}
|
||||
|
||||
private void setAspectRatioSettingsBuildTimeFlagEnabled(boolean enabled) {
|
||||
when(mResources.getBoolean(R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled))
|
||||
.thenReturn(enabled);
|
||||
}
|
||||
|
||||
private void setAspectRatioSettingsDeviceConfigEnabled(String enabled, boolean makeDefault) {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS, enabled, makeDefault);
|
||||
}
|
||||
|
||||
private void setAspectRatioFullscreenBuildTimeFlagEnabled(boolean enabled) {
|
||||
when(mResources.getBoolean(R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled))
|
||||
.thenReturn(enabled);
|
||||
}
|
||||
|
||||
private void setAspectRatioFullscreenDeviceConfigEnabled(String enabled, boolean makeDefault) {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN, enabled, makeDefault);
|
||||
}
|
||||
}
|
||||
@@ -379,7 +379,7 @@ public class FingerprintEnrollProgressViewModelTest {
|
||||
|
||||
// Notify acquire message
|
||||
final int value = 33;
|
||||
mCallbackWrapper.mValue.onPointerDown(value);
|
||||
mCallbackWrapper.mValue.onUdfpsPointerDown(value);
|
||||
assertThat(liveData.getValue()).isEqualTo(value);
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ public class FingerprintEnrollProgressViewModelTest {
|
||||
|
||||
// Notify acquire message
|
||||
final int value = 44;
|
||||
mCallbackWrapper.mValue.onPointerUp(value);
|
||||
mCallbackWrapper.mValue.onUdfpsPointerUp(value);
|
||||
assertThat(liveData.getValue()).isEqualTo(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -24,8 +26,8 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
@@ -42,20 +44,20 @@ import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.bluetooth.BlockingPrefWithSliceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BlockingPrefWithSliceControllerTest {
|
||||
private static final String KEY = "bt_device_slice_category";
|
||||
private static final String TEST_URI_AUTHORITY = "com.android.authority.test";
|
||||
private static final String TEST_URI_AUTHORITY = "com.android.settings";
|
||||
private static final String TEST_EXTRA_INTENT = "EXTRA_INTENT";
|
||||
private static final String TEST_EXTRA_PENDING_INTENT = "EXTRA_PENDING_INTENT";
|
||||
private static final String TEST_INTENT_ACTION = "test";
|
||||
@@ -71,6 +73,8 @@ public class BlockingPrefWithSliceControllerTest {
|
||||
private LiveData<Slice> mLiveData;
|
||||
@Mock
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
@Captor
|
||||
ArgumentCaptor<Preference> mPreferenceArgumentCaptor;
|
||||
|
||||
private Context mContext;
|
||||
private BlockingPrefWithSliceController mController;
|
||||
@@ -130,6 +134,14 @@ public class BlockingPrefWithSliceControllerTest {
|
||||
verify(mController.mPreferenceCategory).addPreference(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onChanged_sliceWithoutValidIntent_makePreferenceUnselectable() {
|
||||
mController.onChanged(buildTestSlice());
|
||||
|
||||
verify(mController.mPreferenceCategory).addPreference(mPreferenceArgumentCaptor.capture());
|
||||
assertThat(mPreferenceArgumentCaptor.getValue().isSelectable()).isFalse();
|
||||
}
|
||||
|
||||
private Slice buildTestSlice() {
|
||||
Uri uri =
|
||||
new Uri.Builder()
|
||||
@@ -141,7 +153,7 @@ public class BlockingPrefWithSliceControllerTest {
|
||||
IconCompat icon = mock(IconCompat.class);
|
||||
listBuilder.addRow(
|
||||
new RowBuilder()
|
||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||
.setTitleItem(icon, ICON_IMAGE)
|
||||
.setTitle(TEST_SLICE_TITLE)
|
||||
.setSubtitle(TEST_SLICE_SUBTITLE)
|
||||
.setPrimaryAction(
|
||||
@@ -153,7 +165,7 @@ public class BlockingPrefWithSliceControllerTest {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
| PendingIntent.FLAG_IMMUTABLE),
|
||||
icon,
|
||||
ListBuilder.ICON_IMAGE,
|
||||
ICON_IMAGE,
|
||||
"")));
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.domain.interactor
|
||||
|
||||
import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintViewModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
/** Fake to be used by other classes to easily fake the FingerprintManager implementation. */
|
||||
class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
|
||||
var enrollableFingerprints: Int = 5
|
||||
var enrolledFingerprintsInternal: MutableList<FingerprintViewModel> = mutableListOf()
|
||||
var challengeToGenerate: Pair<Long, ByteArray> = Pair(-1L, byteArrayOf())
|
||||
var authenticateAttempt = FingerprintAuthAttemptViewModel.Success(1)
|
||||
var pressToAuthEnabled = true
|
||||
|
||||
var sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
TYPE_POWER_BUTTON,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
)
|
||||
|
||||
override suspend fun authenticate(): FingerprintAuthAttemptViewModel {
|
||||
return authenticateAttempt
|
||||
}
|
||||
|
||||
override suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray> {
|
||||
return challengeToGenerate
|
||||
}
|
||||
override val enrolledFingerprints: Flow<List<FingerprintViewModel>> = flow {
|
||||
emit(enrolledFingerprintsInternal)
|
||||
}
|
||||
|
||||
override fun canEnrollFingerprints(numFingerprints: Int): Flow<Boolean> = flow {
|
||||
emit(numFingerprints < enrollableFingerprints)
|
||||
}
|
||||
|
||||
override val maxEnrollableFingerprints: Flow<Int> = flow { emit(enrollableFingerprints) }
|
||||
|
||||
override suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean {
|
||||
return enrolledFingerprintsInternal.remove(fp)
|
||||
}
|
||||
|
||||
override suspend fun renameFingerprint(fp: FingerprintViewModel, newName: String) {}
|
||||
|
||||
override suspend fun hasSideFps(): Boolean {
|
||||
return sensorProps.any { it.isAnySidefpsType }
|
||||
}
|
||||
|
||||
override suspend fun pressToAuthEnabled(): Boolean {
|
||||
return pressToAuthEnabled
|
||||
}
|
||||
|
||||
override suspend fun sensorPropertiesInternal(): List<FingerprintSensorPropertiesInternal> =
|
||||
sensorProps
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.domain.interactor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.hardware.fingerprint.Fingerprint
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintManager.CryptoObject
|
||||
import android.hardware.fingerprint.FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT
|
||||
import android.os.CancellationSignal
|
||||
import android.os.Handler
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintViewModel
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.flow.last
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.anyLong
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.ArgumentMatchers.nullable
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class FingerprintManagerInteractorTest {
|
||||
|
||||
@JvmField @Rule var rule = MockitoJUnit.rule()
|
||||
private lateinit var underTest: FingerprintManagerInteractor
|
||||
private var context: Context = ApplicationProvider.getApplicationContext()
|
||||
private var backgroundDispatcher = StandardTestDispatcher()
|
||||
@Mock private lateinit var fingerprintManager: FingerprintManager
|
||||
@Mock private lateinit var gateKeeperPasswordProvider: GatekeeperPasswordProvider
|
||||
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
private var pressToAuthProvider = { true }
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
underTest =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
gateKeeperPasswordProvider,
|
||||
pressToAuthProvider,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEmptyFingerprints() =
|
||||
testScope.runTest {
|
||||
Mockito.`when`(fingerprintManager.getEnrolledFingerprints(Mockito.anyInt()))
|
||||
.thenReturn(emptyList())
|
||||
|
||||
val emptyFingerprintList: List<Fingerprint> = emptyList()
|
||||
assertThat(underTest.enrolledFingerprints.last()).isEqualTo(emptyFingerprintList)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOneFingerprint() =
|
||||
testScope.runTest {
|
||||
val expected = Fingerprint("Finger 1,", 2, 3L)
|
||||
val fingerprintList: List<Fingerprint> = listOf(expected)
|
||||
Mockito.`when`(fingerprintManager.getEnrolledFingerprints(Mockito.anyInt()))
|
||||
.thenReturn(fingerprintList)
|
||||
|
||||
val list = underTest.enrolledFingerprints.last()
|
||||
assertThat(list.size).isEqualTo(fingerprintList.size)
|
||||
val actual = list[0]
|
||||
assertThat(actual.name).isEqualTo(expected.name)
|
||||
assertThat(actual.fingerId).isEqualTo(expected.biometricId)
|
||||
assertThat(actual.deviceId).isEqualTo(expected.deviceId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanEnrollFingerprint() =
|
||||
testScope.runTest {
|
||||
val mockContext = Mockito.mock(Context::class.java)
|
||||
val resources = Mockito.mock(Resources::class.java)
|
||||
Mockito.`when`(mockContext.resources).thenReturn(resources)
|
||||
Mockito.`when`(resources.getInteger(anyInt())).thenReturn(3)
|
||||
underTest =
|
||||
FingerprintManagerInteractorImpl(
|
||||
mockContext,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
gateKeeperPasswordProvider,
|
||||
pressToAuthProvider,
|
||||
)
|
||||
|
||||
assertThat(underTest.canEnrollFingerprints(2).last()).isTrue()
|
||||
assertThat(underTest.canEnrollFingerprints(3).last()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallenge() =
|
||||
testScope.runTest {
|
||||
val byteArray = byteArrayOf(5, 3, 2)
|
||||
val challenge = 100L
|
||||
val intent = Intent()
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, challenge)
|
||||
Mockito.`when`(
|
||||
gateKeeperPasswordProvider.requestGatekeeperHat(
|
||||
any(Intent::class.java),
|
||||
anyLong(),
|
||||
anyInt()
|
||||
)
|
||||
)
|
||||
.thenReturn(byteArray)
|
||||
|
||||
val generateChallengeCallback: ArgumentCaptor<FingerprintManager.GenerateChallengeCallback> =
|
||||
ArgumentCaptor.forClass(FingerprintManager.GenerateChallengeCallback::class.java)
|
||||
|
||||
var result: Pair<Long, ByteArray?>? = null
|
||||
val job = testScope.launch { result = underTest.generateChallenge(1L) }
|
||||
runCurrent()
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.generateChallenge(anyInt(), capture(generateChallengeCallback))
|
||||
generateChallengeCallback.value.onChallengeGenerated(1, 2, challenge)
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
|
||||
assertThat(result?.first).isEqualTo(challenge)
|
||||
assertThat(result?.second).isEqualTo(byteArray)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveFingerprint_succeeds() =
|
||||
testScope.runTest {
|
||||
val fingerprintViewModelToRemove = FingerprintViewModel("Finger 2", 1, 2L)
|
||||
val fingerprintToRemove = Fingerprint("Finger 2", 1, 2L)
|
||||
|
||||
val removalCallback: ArgumentCaptor<FingerprintManager.RemovalCallback> =
|
||||
ArgumentCaptor.forClass(FingerprintManager.RemovalCallback::class.java)
|
||||
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
|
||||
runCurrent()
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.remove(any(Fingerprint::class.java), anyInt(), capture(removalCallback))
|
||||
removalCallback.value.onRemovalSucceeded(fingerprintToRemove, 1)
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
|
||||
assertThat(result).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveFingerprint_fails() =
|
||||
testScope.runTest {
|
||||
val fingerprintViewModelToRemove = FingerprintViewModel("Finger 2", 1, 2L)
|
||||
val fingerprintToRemove = Fingerprint("Finger 2", 1, 2L)
|
||||
|
||||
val removalCallback: ArgumentCaptor<FingerprintManager.RemovalCallback> =
|
||||
ArgumentCaptor.forClass(FingerprintManager.RemovalCallback::class.java)
|
||||
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
|
||||
runCurrent()
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.remove(any(Fingerprint::class.java), anyInt(), capture(removalCallback))
|
||||
removalCallback.value.onRemovalError(
|
||||
fingerprintToRemove,
|
||||
100,
|
||||
"Oh no, we couldn't find that one"
|
||||
)
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
|
||||
assertThat(result).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRenameFingerprint_succeeds() =
|
||||
testScope.runTest {
|
||||
val fingerprintToRename = FingerprintViewModel("Finger 2", 1, 2L)
|
||||
|
||||
underTest.renameFingerprint(fingerprintToRename, "Woo")
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.rename(eq(fingerprintToRename.fingerId), anyInt(), safeEq("Woo"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAuth_succeeds() =
|
||||
testScope.runTest {
|
||||
val fingerprint = Fingerprint("Woooo", 100, 101L)
|
||||
|
||||
var result: FingerprintAuthAttemptViewModel? = null
|
||||
val job = launch { result = underTest.authenticate() }
|
||||
|
||||
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> =
|
||||
ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback::class.java)
|
||||
|
||||
runCurrent()
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.authenticate(
|
||||
nullable(CryptoObject::class.java),
|
||||
any(CancellationSignal::class.java),
|
||||
capture(authCallback),
|
||||
nullable(Handler::class.java),
|
||||
anyInt()
|
||||
)
|
||||
authCallback.value.onAuthenticationSucceeded(
|
||||
FingerprintManager.AuthenticationResult(null, fingerprint, 1, false)
|
||||
)
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
assertThat(result).isEqualTo(FingerprintAuthAttemptViewModel.Success(fingerprint.biometricId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAuth_lockout() =
|
||||
testScope.runTest {
|
||||
var result: FingerprintAuthAttemptViewModel? = null
|
||||
val job = launch { result = underTest.authenticate() }
|
||||
|
||||
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> =
|
||||
ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback::class.java)
|
||||
|
||||
runCurrent()
|
||||
|
||||
Mockito.verify(fingerprintManager)
|
||||
.authenticate(
|
||||
nullable(CryptoObject::class.java),
|
||||
any(CancellationSignal::class.java),
|
||||
capture(authCallback),
|
||||
nullable(Handler::class.java),
|
||||
anyInt()
|
||||
)
|
||||
authCallback.value.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, "Lockout!!")
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
assertThat(result)
|
||||
.isEqualTo(
|
||||
FingerprintAuthAttemptViewModel.Error(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, "Lockout!!")
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T : Any> safeEq(value: T): T = eq(value) ?: value
|
||||
private fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
|
||||
private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.viewmodel
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.EnrollFirstFingerprint
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintSettingsNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FinishSettings
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FinishSettingsWithResult
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.LaunchConfirmDeviceCredential
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.NextStepViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.ShowSettings
|
||||
import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class FingerprintSettingsNavigationViewModelTest {
|
||||
|
||||
@JvmField @Rule var rule = MockitoJUnit.rule()
|
||||
|
||||
@get:Rule val instantTaskRule = InstantTaskExecutorRule()
|
||||
|
||||
private lateinit var underTest: FingerprintSettingsNavigationViewModel
|
||||
private val defaultUserId = 0
|
||||
private var backgroundDispatcher = StandardTestDispatcher()
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
private lateinit var fakeFingerprintManagerInteractor: FakeFingerprintManagerInteractor
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||
backgroundDispatcher = StandardTestDispatcher()
|
||||
testScope = TestScope(backgroundDispatcher)
|
||||
Dispatchers.setMain(backgroundDispatcher)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoGateKeeper_launchesConfirmDeviceCredential() =
|
||||
testScope.runTest {
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
runCurrent()
|
||||
assertThat(nextStep).isEqualTo(LaunchConfirmDeviceCredential(defaultUserId))
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConfirmDevice_fails() =
|
||||
testScope.runTest {
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(false, null)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun confirmDeviceSuccess_noGateKeeper() =
|
||||
testScope.runTest {
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, null)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun confirmDeviceSuccess_launchesEnrollment_ifNoPreviousEnrollments() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(EnrollFirstFingerprint(defaultUserId, 10L, null, null))
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollment_fails() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirstFailure("We failed!!")
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollment_failsWithReason() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
val failStr = "We failed!!"
|
||||
val failReason = 101
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirstFailure(failStr, failReason)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(FinishSettingsWithResult(failReason, failStr))
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollmentSucceeds_noToken() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirst(null, null)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(FinishSettings("Error, empty token"))
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollmentSucceeds_noKeyChallenge() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
val byteArray = ByteArray(1) { 3 }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirst(byteArray, null)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(FinishSettings("Error, empty keyChallenge"))
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollment_succeeds() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = testScope.launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
val byteArray = ByteArray(1) { 3 }
|
||||
val keyChallenge = 89L
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirst(byteArray, keyChallenge)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(ShowSettings)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun enrollAdditionalFingerprints_fails() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
fakeFingerprintManagerInteractor.challengeToGenerate = Pair(4L, byteArrayOf(3, 3, 1))
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
runCurrent()
|
||||
underTest.onEnrollAdditionalFailure()
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun enrollAdditional_success() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollSuccess()
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(ShowSettings)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun confirmDeviceCredential_withEnrolledFingerprint_showsSettings() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
fakeFingerprintManagerInteractor.challengeToGenerate = Pair(10L, byteArrayOf(1, 2, 3))
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isEqualTo(ShowSettings)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.viewmodel
|
||||
|
||||
import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintSettingsNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintSettingsViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.viewmodel.PreferenceViewModel
|
||||
import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class FingerprintSettingsViewModelTest {
|
||||
|
||||
@JvmField @Rule var rule = MockitoJUnit.rule()
|
||||
|
||||
@get:Rule val instantTaskRule = InstantTaskExecutorRule()
|
||||
|
||||
private lateinit var underTest: FingerprintSettingsViewModel
|
||||
private lateinit var navigationViewModel: FingerprintSettingsNavigationViewModel
|
||||
private val defaultUserId = 0
|
||||
private var backgroundDispatcher = StandardTestDispatcher()
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
private lateinit var fakeFingerprintManagerInteractor: FakeFingerprintManagerInteractor
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||
backgroundDispatcher = StandardTestDispatcher()
|
||||
testScope = TestScope(backgroundDispatcher)
|
||||
Dispatchers.setMain(backgroundDispatcher)
|
||||
|
||||
navigationViewModel =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun authenticate_DoesNotRun_ifOptical() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptViewModel? = null
|
||||
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
|
||||
|
||||
underTest.shouldAuthenticate(true)
|
||||
// Ensure we are showing settings
|
||||
navigationViewModel.onConfirmDevice(true, 10L)
|
||||
|
||||
runCurrent()
|
||||
advanceTimeBy(400)
|
||||
|
||||
assertThat(authAttempt).isNull()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun authenticate_DoesNotRun_ifUltrasonic() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptViewModel? = null
|
||||
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
|
||||
|
||||
underTest.shouldAuthenticate(true)
|
||||
navigationViewModel.onConfirmDevice(true, 10L)
|
||||
advanceTimeBy(400)
|
||||
runCurrent()
|
||||
|
||||
assertThat(authAttempt).isNull()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun authenticate_DoesRun_ifNotUdfps() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
val success = FingerprintAuthAttemptViewModel.Success(1)
|
||||
fakeFingerprintManagerInteractor.authenticateAttempt = success
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptViewModel? = null
|
||||
|
||||
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
|
||||
underTest.shouldAuthenticate(true)
|
||||
navigationViewModel.onConfirmDevice(true, 10L)
|
||||
advanceTimeBy(400)
|
||||
runCurrent()
|
||||
|
||||
assertThat(authAttempt).isEqualTo(success)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deleteDialog_showAndDismiss() = runTest {
|
||||
val fingerprintToDelete = FingerprintViewModel("A", 1, 10L)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf(fingerprintToDelete)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
|
||||
var dialog: PreferenceViewModel? = null
|
||||
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
|
||||
|
||||
// Move to the ShowSettings state
|
||||
navigationViewModel.onConfirmDevice(true, 10L)
|
||||
runCurrent()
|
||||
underTest.onDeleteClicked(fingerprintToDelete)
|
||||
runCurrent()
|
||||
|
||||
assertThat(dialog is PreferenceViewModel.DeleteDialog)
|
||||
assertThat(dialog).isEqualTo(PreferenceViewModel.DeleteDialog(fingerprintToDelete))
|
||||
|
||||
underTest.deleteFingerprint(fingerprintToDelete)
|
||||
underTest.onDeleteDialogFinished()
|
||||
runCurrent()
|
||||
|
||||
assertThat(dialog).isNull()
|
||||
|
||||
dialogJob.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.settings.inputmethod;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class KeyboardSettingsFeatureProviderImplTest {
|
||||
|
||||
private Context mContext;
|
||||
private KeyboardSettingsFeatureProviderImpl mFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureProvider = new KeyboardSettingsFeatureProviderImpl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFirmwareUpdate_defaultValue_returnsFalse() {
|
||||
assertThat(mFeatureProvider.supportsFirmwareUpdate()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addFirmwareUpdateCategory_defaultValue_returnsFalse() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
|
||||
assertThat(mFeatureProvider.addFirmwareUpdateCategory(mContext, screen)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getActionKeyIcon_defaultValue_returnsNull() {
|
||||
assertThat(mFeatureProvider.getActionKeyIcon(mContext)).isNull();
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,12 @@ package com.android.settings.localepicker;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -39,7 +37,6 @@ import org.mockito.MockitoAnnotations;
|
||||
public class LocaleHelperPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
@Mock
|
||||
private FooterPreference mMockFooterPreference;
|
||||
@@ -52,16 +49,11 @@ public class LocaleHelperPreferenceControllerTest {
|
||||
}
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(mContext);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateFooterPreference_setFooterPreference_hasClickAction() {
|
||||
mLocaleHelperPreferenceController.updateFooterPreference(mMockFooterPreference);
|
||||
verify(mMockFooterPreference).setLearnMoreText(anyString());
|
||||
mMockFooterPreference.setLearnMoreAction(v -> {
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(
|
||||
mContext, SettingsEnums.ACTION_LANGUAGES_LEARN_MORE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,30 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static com.android.settings.network.SubscriptionUtil.KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME;
|
||||
import static com.android.settings.network.SubscriptionUtil.SUB_ID;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
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.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@@ -179,7 +183,7 @@ public class SubscriptionUtilTest {
|
||||
@Ignore
|
||||
@Test
|
||||
public void getUniqueDisplayNames_identicalCarriers_fourDigitsUsed() {
|
||||
// Both subscriptoins have the same display name.
|
||||
// Both subscriptions have the same display name.
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
when(info1.getSubscriptionId()).thenReturn(SUBID_1);
|
||||
@@ -209,7 +213,7 @@ public class SubscriptionUtilTest {
|
||||
@Ignore
|
||||
@Test
|
||||
public void getUniqueDisplayNames_identicalCarriersAfterTrim_fourDigitsUsed() {
|
||||
// Both subscriptoins have the same display name.
|
||||
// Both subscriptions have the same display name.
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
when(info1.getSubscriptionId()).thenReturn(SUBID_1);
|
||||
@@ -238,8 +242,8 @@ public class SubscriptionUtilTest {
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void getUniqueDisplayNames_phoneNumberBlocked_subscriptoinIdFallback() {
|
||||
// Both subscriptoins have the same display name.
|
||||
public void getUniqueDisplayNames_phoneNumberBlocked_subscriptionIdFallback() {
|
||||
// Both subscriptions have the same display name.
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
when(info1.getSubscriptionId()).thenReturn(SUBID_1);
|
||||
@@ -267,9 +271,9 @@ public class SubscriptionUtilTest {
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void getUniqueDisplayNames_phoneNumberIdentical_subscriptoinIdFallback() {
|
||||
public void getUniqueDisplayNames_phoneNumberIdentical_subscriptionIdFallback() {
|
||||
// TODO have three here from the same carrier
|
||||
// Both subscriptoins have the same display name.
|
||||
// Both subscriptions have the same display name.
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
|
||||
@@ -444,6 +448,68 @@ public class SubscriptionUtilTest {
|
||||
assertTrue(TextUtils.isEmpty(name));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUniqueDisplayName_hasRecord_useRecordBeTheResult() {
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
when(info1.getSubscriptionId()).thenReturn(SUBID_1);
|
||||
when(info2.getSubscriptionId()).thenReturn(SUBID_2);
|
||||
when(info1.getDisplayName()).thenReturn(CARRIER_1);
|
||||
when(info2.getDisplayName()).thenReturn(CARRIER_1);
|
||||
when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(
|
||||
Arrays.asList(info1, info2));
|
||||
|
||||
SharedPreferences sp = mock(SharedPreferences.class);
|
||||
when(mContext.getSharedPreferences(
|
||||
KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME, Context.MODE_PRIVATE)).thenReturn(sp);
|
||||
when(sp.getString(eq(SUB_ID + SUBID_1), anyString())).thenReturn(CARRIER_1 + " 6789");
|
||||
when(sp.getString(eq(SUB_ID + SUBID_2), anyString())).thenReturn(CARRIER_1 + " 4321");
|
||||
|
||||
|
||||
final CharSequence nameOfSub1 =
|
||||
SubscriptionUtil.getUniqueSubscriptionDisplayName(info1, mContext);
|
||||
final CharSequence nameOfSub2 =
|
||||
SubscriptionUtil.getUniqueSubscriptionDisplayName(info2, mContext);
|
||||
|
||||
assertThat(nameOfSub1).isNotNull();
|
||||
assertThat(nameOfSub2).isNotNull();
|
||||
assertEquals(CARRIER_1 + " 6789", nameOfSub1.toString());
|
||||
assertEquals(CARRIER_1 + " 4321", nameOfSub2.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUniqueDisplayName_hasRecordAndNameIsChanged_doesNotUseRecordBeTheResult() {
|
||||
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
|
||||
when(info1.getSubscriptionId()).thenReturn(SUBID_1);
|
||||
when(info2.getSubscriptionId()).thenReturn(SUBID_2);
|
||||
when(info1.getDisplayName()).thenReturn(CARRIER_1);
|
||||
when(info2.getDisplayName()).thenReturn(CARRIER_2);
|
||||
when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(
|
||||
Arrays.asList(info1, info2));
|
||||
|
||||
SharedPreferences sp = mock(SharedPreferences.class);
|
||||
SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
|
||||
when(mContext.getSharedPreferences(
|
||||
KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME, Context.MODE_PRIVATE)).thenReturn(sp);
|
||||
when(sp.edit()).thenReturn(editor);
|
||||
when(editor.remove(anyString())).thenReturn(editor);
|
||||
|
||||
when(sp.getString(eq(SUB_ID + SUBID_1), anyString())).thenReturn(CARRIER_1 + " 6789");
|
||||
when(sp.getString(eq(SUB_ID + SUBID_2), anyString())).thenReturn(CARRIER_1 + " 4321");
|
||||
|
||||
|
||||
final CharSequence nameOfSub1 =
|
||||
SubscriptionUtil.getUniqueSubscriptionDisplayName(info1, mContext);
|
||||
final CharSequence nameOfSub2 =
|
||||
SubscriptionUtil.getUniqueSubscriptionDisplayName(info2, mContext);
|
||||
|
||||
assertThat(nameOfSub1).isNotNull();
|
||||
assertThat(nameOfSub2).isNotNull();
|
||||
assertEquals(CARRIER_1 + " 6789", nameOfSub1.toString());
|
||||
assertEquals(CARRIER_2.toString(), nameOfSub2.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInactiveInsertedPSim_nullSubInfo_doesNotCrash() {
|
||||
assertThat(SubscriptionUtil.isInactiveInsertedPSim(null)).isFalse();
|
||||
@@ -466,4 +532,60 @@ public class SubscriptionUtilTest {
|
||||
|
||||
assertTrue(SubscriptionUtil.isSimHardwareVisible(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_matchesRule1_returnTrue() {
|
||||
String originalName = "originalName";
|
||||
String cacheString = "originalName 1234";
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_matchesRule2_returnTrue() {
|
||||
String originalName = "original Name";
|
||||
String cacheString = originalName + " " + 1234;
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_nameIsEmpty1_returnFalse() {
|
||||
String originalName = "original Name";
|
||||
String cacheString = "";
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_nameIsEmpty2_returnFalse() {
|
||||
String originalName = "";
|
||||
String cacheString = "originalName 1234";
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_nameIsDifferent_returnFalse() {
|
||||
String originalName = "original Name";
|
||||
String cacheString = "originalName 1234";
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_noNumber_returnFalse() {
|
||||
String originalName = "original Name";
|
||||
String cacheString = originalName;
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidCachedDisplayName_noSpace_returnFalse() {
|
||||
String originalName = "original Name";
|
||||
String cacheString = originalName;
|
||||
|
||||
assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -49,6 +52,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class UiccSlotUtilTest {
|
||||
@@ -738,6 +742,25 @@ public class UiccSlotUtilTest {
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performSwitchToSlot_setSimSlotMapping() throws UiccSlotsException {
|
||||
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsBNoOrding();
|
||||
|
||||
UiccSlotUtil.performSwitchToSlot(mTelephonyManager, uiccSlotMappings, mContext);
|
||||
|
||||
verify(mTelephonyManager).setSimSlotMapping(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceiveSimSlotChangeReceiver_receiveAction_timerCountDown() {
|
||||
CountDownLatch latch = spy(new CountDownLatch(1));
|
||||
UiccSlotUtil.SimSlotChangeReceiver receive = new UiccSlotUtil.SimSlotChangeReceiver(latch);
|
||||
|
||||
receive.onReceive(mContext, new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
|
||||
|
||||
verify(latch).countDown();
|
||||
}
|
||||
|
||||
private void compareTwoUiccSlotMappings(Collection<UiccSlotMapping> testUiccSlotMappings,
|
||||
Collection<UiccSlotMapping> verifyUiccSlotMappings) {
|
||||
assertThat(testUiccSlotMappings.size()).isEqualTo(verifyUiccSlotMappings.size());
|
||||
|
||||
@@ -21,15 +21,20 @@ import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_U
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.telephony.data.ApnSetting;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
@@ -63,7 +68,7 @@ public class MmsMessagePreferenceControllerTest {
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
|
||||
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
mPreference = spy(new SwitchPreference(mContext));
|
||||
mController = new MmsMessagePreferenceController(mContext, "mms_message");
|
||||
mController.init(SUB_ID);
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
@@ -118,4 +123,20 @@ public class MmsMessagePreferenceControllerTest {
|
||||
verify(mTelephonyManager).setMobileDataPolicyEnabled(
|
||||
TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_updatePreferenceUiState() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
|
||||
preferenceScreen.addPreference(mPreference);
|
||||
mController.displayPreference(preferenceScreen);
|
||||
|
||||
mController.onStart();
|
||||
|
||||
// First is preference initialization, and second is in onStart();
|
||||
verify(mPreference, times(2)).setChecked(anyBoolean());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.CellIdentity;
|
||||
import android.telephony.CellIdentityGsm;
|
||||
@@ -37,6 +36,7 @@ import android.telephony.CellSignalStrengthGsm;
|
||||
import android.telephony.CellSignalStrengthLte;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
@@ -310,4 +310,13 @@ public class NetworkSelectSettingsTest {
|
||||
cellInfoGsm.setCellSignalStrength(cssg);
|
||||
return cellInfoGsm;
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void onPreferenceTreeClick_notNetworkOperatorPreference_noCrash() {
|
||||
mNetworkSelectSettings.onCreateInitialization();
|
||||
mNetworkSelectSettings.enablePreferenceScreen(true);
|
||||
|
||||
mNetworkSelectSettings.onPreferenceTreeClick(new Preference(mContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
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 androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SaveAndFinishWorkerTest {
|
||||
@Test
|
||||
public void testSetRequestWriteRepairModePassword_setLockCredentialFail() {
|
||||
int userId = 0;
|
||||
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
|
||||
var chosenCredential = LockscreenCredential.createPassword("1234");
|
||||
var currentCredential = LockscreenCredential.createNone();
|
||||
var worker = new SaveAndFinishWorker();
|
||||
var lpu = mock(LockPatternUtils.class);
|
||||
|
||||
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(false);
|
||||
|
||||
worker.setRequestWriteRepairModePassword(true);
|
||||
worker.prepare(lpu, chosenCredential, currentCredential, userId);
|
||||
var result = worker.saveAndVerifyInBackground();
|
||||
|
||||
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
|
||||
verify(lpu, never()).verifyCredential(chosenCredential, userId, flags);
|
||||
assertThat(result.first).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRequestWriteRepairModePassword_verifyCredentialFail() {
|
||||
int userId = 0;
|
||||
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
|
||||
var chosenCredential = LockscreenCredential.createPassword("1234");
|
||||
var currentCredential = LockscreenCredential.createNone();
|
||||
var worker = new SaveAndFinishWorker();
|
||||
var lpu = mock(LockPatternUtils.class);
|
||||
var response = VerifyCredentialResponse.fromError();
|
||||
|
||||
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
|
||||
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
|
||||
|
||||
worker.setRequestWriteRepairModePassword(true);
|
||||
worker.prepare(lpu, chosenCredential, currentCredential, userId);
|
||||
var result = worker.saveAndVerifyInBackground();
|
||||
|
||||
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
|
||||
verify(lpu).verifyCredential(chosenCredential, userId, flags);
|
||||
assertThat(result.first).isTrue();
|
||||
assertThat(result.second.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, true))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRequestWriteRepairModePassword_verifyCredentialSucceed() {
|
||||
int userId = 0;
|
||||
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
|
||||
var chosenCredential = LockscreenCredential.createPassword("1234");
|
||||
var currentCredential = LockscreenCredential.createNone();
|
||||
var worker = new SaveAndFinishWorker();
|
||||
var lpu = mock(LockPatternUtils.class);
|
||||
var response = new VerifyCredentialResponse.Builder().build();
|
||||
|
||||
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
|
||||
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
|
||||
|
||||
worker.setRequestWriteRepairModePassword(true);
|
||||
worker.prepare(lpu, chosenCredential, currentCredential, userId);
|
||||
var result = worker.saveAndVerifyInBackground();
|
||||
|
||||
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
|
||||
verify(lpu).verifyCredential(chosenCredential, userId, flags);
|
||||
assertThat(result.first).isTrue();
|
||||
assertThat(result.second.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, false))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRequestWriteRepairModePassword_verifyCredentialSucceed_noGkPwHandle() {
|
||||
int userId = 0;
|
||||
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW
|
||||
| LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE;
|
||||
var chosenCredential = LockscreenCredential.createPassword("1234");
|
||||
var currentCredential = LockscreenCredential.createNone();
|
||||
var worker = new SaveAndFinishWorker();
|
||||
var lpu = mock(LockPatternUtils.class);
|
||||
var response = new VerifyCredentialResponse.Builder().build();
|
||||
|
||||
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
|
||||
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
|
||||
|
||||
worker.setRequestWriteRepairModePassword(true);
|
||||
worker.setRequestGatekeeperPasswordHandle(true);
|
||||
worker.prepare(lpu, chosenCredential, currentCredential, userId);
|
||||
var result = worker.saveAndVerifyInBackground();
|
||||
|
||||
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
|
||||
verify(lpu).verifyCredential(chosenCredential, userId, flags);
|
||||
assertThat(result.first).isTrue();
|
||||
assertThat(result.second.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, false))
|
||||
.isTrue();
|
||||
assertThat(result.second.getLongExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, -1))
|
||||
.isEqualTo(-1);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.LocaleList;
|
||||
@@ -52,7 +51,6 @@ public class NumberingSystemItemControllerTest {
|
||||
private NumberingPreferencesFragment mFragment;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
private LocaleList mCacheLocale;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
@@ -61,7 +59,6 @@ public class NumberingSystemItemControllerTest {
|
||||
Looper.prepare();
|
||||
}
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFragment = spy(new NumberingPreferencesFragment());
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mApplicationContext);
|
||||
mPreferenceScreen = preferenceManager.createPreferenceScreen(mApplicationContext);
|
||||
@@ -97,10 +94,6 @@ public class NumberingSystemItemControllerTest {
|
||||
}
|
||||
|
||||
assertTrue(isCallingStartActivity);
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(
|
||||
mApplicationContext,
|
||||
SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES,
|
||||
"I_am_the_key");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,9 +114,6 @@ public class NumberingSystemItemControllerTest {
|
||||
mController.handlePreferenceTreeClick(preference);
|
||||
|
||||
verify(mFragment).setArguments(any());
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(
|
||||
mApplicationContext, SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES,
|
||||
"test_key");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.settings.aware.AwareFeatureProvider;
|
||||
import com.android.settings.biometrics.face.FaceFeatureProvider;
|
||||
import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
|
||||
import com.android.settings.bluetooth.BluetoothFeatureProvider;
|
||||
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardFeatureProvider;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
||||
import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider;
|
||||
@@ -37,6 +38,7 @@ import com.android.settings.fuelgauge.BatteryStatusFeatureProvider;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
|
||||
import com.android.settings.inputmethod.KeyboardSettingsFeatureProvider;
|
||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||
import com.android.settings.overlay.DockUpdaterFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
@@ -90,6 +92,8 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
|
||||
public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
|
||||
public WifiFeatureProvider mWifiFeatureProvider;
|
||||
public KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
|
||||
public StylusFeatureProvider mStylusFeatureProvider;
|
||||
|
||||
/**
|
||||
* Call this in {@code @Before} method of the test class to use fake factory.
|
||||
@@ -133,6 +137,8 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class);
|
||||
mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
|
||||
mWifiFeatureProvider = mock(WifiFeatureProvider.class);
|
||||
mKeyboardSettingsFeatureProvider = mock(KeyboardSettingsFeatureProvider.class);
|
||||
mStylusFeatureProvider = mock(StylusFeatureProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,7 +162,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatterySettingsFeatureProvider getBatterySettingsFeatureProvider(Context context) {
|
||||
public BatterySettingsFeatureProvider getBatterySettingsFeatureProvider() {
|
||||
return batterySettingsFeatureProvider;
|
||||
}
|
||||
|
||||
@@ -289,4 +295,14 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
public WifiFeatureProvider getWifiFeatureProvider() {
|
||||
return mWifiFeatureProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyboardSettingsFeatureProvider getKeyboardSettingsFeatureProvider() {
|
||||
return mKeyboardSettingsFeatureProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StylusFeatureProvider getStylusFeatureProvider() {
|
||||
return mStylusFeatureProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.details;
|
||||
|
||||
import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
|
||||
import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_ETHERNET;
|
||||
import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
|
||||
import static android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
|
||||
|
||||
import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.wifitrackerlib.HotspotNetworkEntry;
|
||||
import com.android.wifitrackerlib.WifiEntry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class WifiNetworkDetailsViewModelTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Spy
|
||||
Application mApplication = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
MutableLiveData<WifiNetworkDetailsViewModel.HotspotNetworkData> mHotspotNetworkData;
|
||||
@Mock
|
||||
HotspotNetworkEntry mHotspotNetworkEntry;
|
||||
|
||||
WifiNetworkDetailsViewModel mViewModel;
|
||||
ArgumentCaptor<WifiNetworkDetailsViewModel.HotspotNetworkData> mHotspotNetworkDataCaptor =
|
||||
ArgumentCaptor.forClass(WifiNetworkDetailsViewModel.HotspotNetworkData.class);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mViewModel = new WifiNetworkDetailsViewModel(mApplication);
|
||||
mViewModel.mHotspotNetworkData = mHotspotNetworkData;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWifiEntry_notHotspotNetworkEntry_postValueNull() {
|
||||
mViewModel.setWifiEntry(mock(WifiEntry.class));
|
||||
|
||||
verify(mHotspotNetworkData).postValue(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWifiEntry_hotspotNetworkEntryWifi_postValueCorrect() {
|
||||
when(mHotspotNetworkEntry.getNetworkType()).thenReturn(NETWORK_TYPE_WIFI);
|
||||
when(mHotspotNetworkEntry.getUpstreamConnectionStrength()).thenReturn(WIFI_LEVEL_MAX);
|
||||
when(mHotspotNetworkEntry.getBatteryPercentage()).thenReturn(100);
|
||||
when(mHotspotNetworkEntry.isBatteryCharging()).thenReturn(false);
|
||||
|
||||
|
||||
mViewModel.setWifiEntry(mHotspotNetworkEntry);
|
||||
|
||||
verify(mHotspotNetworkData).postValue(mHotspotNetworkDataCaptor.capture());
|
||||
WifiNetworkDetailsViewModel.HotspotNetworkData data = mHotspotNetworkDataCaptor.getValue();
|
||||
assertThat(data.getNetworkType()).isEqualTo(NETWORK_TYPE_WIFI);
|
||||
assertThat(data.getUpstreamConnectionStrength()).isEqualTo(WIFI_LEVEL_MAX);
|
||||
assertThat(data.getBatteryPercentage()).isEqualTo(100);
|
||||
assertThat(data.isBatteryCharging()).isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWifiEntry_hotspotNetworkEntryMobileData_postValueCorrect() {
|
||||
when(mHotspotNetworkEntry.getNetworkType()).thenReturn(NETWORK_TYPE_CELLULAR);
|
||||
when(mHotspotNetworkEntry.getUpstreamConnectionStrength())
|
||||
.thenReturn(SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
when(mHotspotNetworkEntry.getBatteryPercentage()).thenReturn(0);
|
||||
when(mHotspotNetworkEntry.isBatteryCharging()).thenReturn(true);
|
||||
|
||||
|
||||
mViewModel.setWifiEntry(mHotspotNetworkEntry);
|
||||
|
||||
verify(mHotspotNetworkData).postValue(mHotspotNetworkDataCaptor.capture());
|
||||
WifiNetworkDetailsViewModel.HotspotNetworkData data = mHotspotNetworkDataCaptor.getValue();
|
||||
assertThat(data.getNetworkType()).isEqualTo(NETWORK_TYPE_CELLULAR);
|
||||
assertThat(data.getUpstreamConnectionStrength()).isEqualTo(SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
assertThat(data.getBatteryPercentage()).isEqualTo(0);
|
||||
assertThat(data.isBatteryCharging()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWifiEntry_hotspotNetworkEntryEthernet_postValueCorrect() {
|
||||
when(mHotspotNetworkEntry.getNetworkType()).thenReturn(NETWORK_TYPE_ETHERNET);
|
||||
when(mHotspotNetworkEntry.getBatteryPercentage()).thenReturn(50);
|
||||
when(mHotspotNetworkEntry.isBatteryCharging()).thenReturn(true);
|
||||
|
||||
|
||||
mViewModel.setWifiEntry(mHotspotNetworkEntry);
|
||||
|
||||
verify(mHotspotNetworkData).postValue(mHotspotNetworkDataCaptor.capture());
|
||||
WifiNetworkDetailsViewModel.HotspotNetworkData data = mHotspotNetworkDataCaptor.getValue();
|
||||
assertThat(data.getNetworkType()).isEqualTo(NETWORK_TYPE_ETHERNET);
|
||||
assertThat(data.getBatteryPercentage()).isEqualTo(50);
|
||||
assertThat(data.isBatteryCharging()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSecuritySummary_returnNotNull() {
|
||||
assertThat(mViewModel.getHotspotNetworkData()).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.dpp;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class WifiQrCodeTest {
|
||||
@Test
|
||||
public void testZxParsing_validCode() {
|
||||
WifiNetworkConfig config = new WifiQrCode("WIFI:S:testAbC;T:nopass").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("testAbC");
|
||||
assertThat(config.getSecurity()).isEqualTo("nopass");
|
||||
|
||||
config = new WifiQrCode(
|
||||
"WIFI:S:reallyLONGone;T:WEP;P:somepasswo#%^**123rd").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("reallyLONGone");
|
||||
assertThat(config.getSecurity()).isEqualTo("WEP");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("somepasswo#%^**123rd");
|
||||
|
||||
config = new WifiQrCode("WIFI:S:anotherone;T:WPA;P:3#=3j9asicla").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("anotherone");
|
||||
assertThat(config.getSecurity()).isEqualTo("WPA");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("3#=3j9asicla");
|
||||
|
||||
config = new WifiQrCode("WIFI:S:xx;T:SAE;P:a").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("xx");
|
||||
assertThat(config.getSecurity()).isEqualTo("SAE");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZxParsing_invalidCodeButShouldWork() {
|
||||
WifiNetworkConfig config = new WifiQrCode(
|
||||
"WIFI:S:testAbC; T:nopass").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("testAbC");
|
||||
assertThat(config.getSecurity()).isEqualTo("nopass");
|
||||
|
||||
config = new WifiQrCode(
|
||||
"WIFI:S:reallyLONGone;T:WEP; P:somepassword").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("reallyLONGone");
|
||||
assertThat(config.getSecurity()).isEqualTo("WEP");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("somepassword");
|
||||
|
||||
config = new WifiQrCode("WIFI: S:anotherone;T:WPA;P:abcdefghihklmn").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("anotherone");
|
||||
assertThat(config.getSecurity()).isEqualTo("WPA");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("abcdefghihklmn");
|
||||
|
||||
config = new WifiQrCode("WIFI: S:xx; T:SAE; P:a").getWifiNetworkConfig();
|
||||
assertThat(config.getSsid()).isEqualTo("xx");
|
||||
assertThat(config.getSecurity()).isEqualTo("SAE");
|
||||
assertThat(config.getPreSharedKey()).isEqualTo("a");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.repository;
|
||||
|
||||
import static android.app.PendingIntent.FLAG_IMMUTABLE;
|
||||
|
||||
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.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
|
||||
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class SharedConnectivityRepositoryTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Spy
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
private SharedConnectivityManager mManager;
|
||||
|
||||
private SharedConnectivityRepository mRepository;
|
||||
private PendingIntent mIntent = PendingIntent
|
||||
.getActivity(mContext, 0, new Intent("test"), FLAG_IMMUTABLE);
|
||||
private SharedConnectivitySettingsState mState = new SharedConnectivitySettingsState.Builder()
|
||||
.setInstantTetherSettingsPendingIntent(mIntent).build();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(mContext.getSystemService(SharedConnectivityManager.class)).thenReturn(mManager);
|
||||
when(mManager.getSettingsState()).thenReturn(mState);
|
||||
|
||||
mRepository = spy(new SharedConnectivityRepository(mContext, true /* isConfigEnabled */));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_configEnabled_registerCallback() {
|
||||
verify(mManager).registerCallback(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_configNotEnabled_doNotRegisterCallback() {
|
||||
SharedConnectivityManager manager = mock(SharedConnectivityManager.class);
|
||||
when(mContext.getSystemService(SharedConnectivityManager.class)).thenReturn(manager);
|
||||
|
||||
mRepository = new SharedConnectivityRepository(mContext, false /* isConfigEnabled */);
|
||||
|
||||
verify(manager, never()).registerCallback(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isServiceAvailable_configEnabled_returnTrue() {
|
||||
mRepository = new SharedConnectivityRepository(mContext, true /* isConfigEnabled */);
|
||||
|
||||
assertThat(mRepository.isServiceAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isServiceAvailable_configNotEnabled_returnFalse() {
|
||||
mRepository = new SharedConnectivityRepository(mContext, false /* isConfigEnabled */);
|
||||
|
||||
assertThat(mRepository.isServiceAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSettingsState_isNotNull() {
|
||||
assertThat(mRepository.getSettingsState()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLaunchSettings_managerNull_doNothing() {
|
||||
when(mContext.getSystemService(SharedConnectivityManager.class)).thenReturn(null);
|
||||
mRepository = spy(new SharedConnectivityRepository(mContext, true /* isConfigEnabled */));
|
||||
|
||||
mRepository.handleLaunchSettings();
|
||||
|
||||
verify(mRepository, never()).sendSettingsIntent(mIntent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLaunchSettings_stageNull_doNothing() {
|
||||
when(mManager.getSettingsState()).thenReturn(null);
|
||||
|
||||
mRepository.handleLaunchSettings();
|
||||
|
||||
verify(mRepository, never()).sendSettingsIntent(mIntent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLaunchSettings_intentNull_doNothing() {
|
||||
mState = new SharedConnectivitySettingsState.Builder()
|
||||
.setInstantTetherSettingsPendingIntent(null).build();
|
||||
when(mManager.getSettingsState()).thenReturn(mState);
|
||||
|
||||
mRepository.handleLaunchSettings();
|
||||
|
||||
verify(mRepository, never()).sendSettingsIntent(mIntent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLaunchSettings_allReady_sendSettingsIntent() {
|
||||
mRepository.handleLaunchSettings();
|
||||
|
||||
verify(mRepository).sendSettingsIntent(mIntent);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,9 @@ import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2
|
||||
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ_5GHZ;
|
||||
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_5GHZ;
|
||||
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
|
||||
import static com.android.settings.wifi.tether.WifiHotspotSpeedViewModel.RES_SPEED_5G_SUMMARY;
|
||||
import static com.android.settings.wifi.tether.WifiHotspotSpeedViewModel.RES_SPEED_6G_SUMMARY;
|
||||
import static com.android.settings.wifi.tether.WifiHotspotSpeedViewModel.RES_SUMMARY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -128,7 +131,9 @@ public class WifiHotspotSpeedViewModelTest {
|
||||
mViewModel.on6gAvailableChanged(true);
|
||||
|
||||
verify(mSpeedInfoMapData).setValue(mViewModel.mSpeedInfoMap);
|
||||
assertThat(mViewModel.mSpeedInfoMap.get(SPEED_6GHZ).mIsEnabled).isTrue();
|
||||
WifiHotspotSpeedViewModel.SpeedInfo speedInfo = mViewModel.mSpeedInfoMap.get(SPEED_6GHZ);
|
||||
assertThat(speedInfo.mIsEnabled).isTrue();
|
||||
assertThat(speedInfo.mSummary).isEqualTo(mContext.getString(RES_SPEED_6G_SUMMARY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -139,7 +144,9 @@ public class WifiHotspotSpeedViewModelTest {
|
||||
mViewModel.on6gAvailableChanged(false);
|
||||
|
||||
verify(mSpeedInfoMapData).setValue(mViewModel.mSpeedInfoMap);
|
||||
assertThat(mViewModel.mSpeedInfoMap.get(SPEED_6GHZ).mIsEnabled).isFalse();
|
||||
WifiHotspotSpeedViewModel.SpeedInfo speedInfo = mViewModel.mSpeedInfoMap.get(SPEED_6GHZ);
|
||||
assertThat(speedInfo.mIsEnabled).isFalse();
|
||||
assertThat(speedInfo.mSummary).isEqualTo(mContext.getString(RES_SUMMARY_UNAVAILABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,7 +157,9 @@ public class WifiHotspotSpeedViewModelTest {
|
||||
mViewModel.on5gAvailableChanged(true);
|
||||
|
||||
verify(mSpeedInfoMapData).setValue(mViewModel.mSpeedInfoMap);
|
||||
assertThat(mViewModel.mSpeedInfoMap.get(SPEED_5GHZ).mIsEnabled).isTrue();
|
||||
WifiHotspotSpeedViewModel.SpeedInfo speedInfo = mViewModel.mSpeedInfoMap.get(SPEED_5GHZ);
|
||||
assertThat(speedInfo.mIsEnabled).isTrue();
|
||||
assertThat(speedInfo.mSummary).isEqualTo(mContext.getString(RES_SPEED_5G_SUMMARY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -161,7 +170,9 @@ public class WifiHotspotSpeedViewModelTest {
|
||||
mViewModel.on5gAvailableChanged(false);
|
||||
|
||||
verify(mSpeedInfoMapData).setValue(mViewModel.mSpeedInfoMap);
|
||||
assertThat(mViewModel.mSpeedInfoMap.get(SPEED_5GHZ).mIsEnabled).isFalse();
|
||||
WifiHotspotSpeedViewModel.SpeedInfo speedInfo = mViewModel.mSpeedInfoMap.get(SPEED_5GHZ);
|
||||
assertThat(speedInfo.mIsEnabled).isFalse();
|
||||
assertThat(speedInfo.mSummary).isEqualTo(mContext.getString(RES_SUMMARY_UNAVAILABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.settings.wifi.tether;
|
||||
|
||||
import static com.android.settings.wifi.tether.WifiTetherViewModel.RES_INSTANT_HOTSPOT_SUMMARY_OFF;
|
||||
import static com.android.settings.wifi.tether.WifiTetherViewModel.RES_INSTANT_HOTSPOT_SUMMARY_ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -23,12 +26,15 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Application;
|
||||
import android.net.wifi.SoftApConfiguration;
|
||||
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.wifi.repository.SharedConnectivityRepository;
|
||||
import com.android.settings.wifi.repository.WifiHotspotRepository;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -36,6 +42,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@@ -45,8 +52,8 @@ import java.util.concurrent.Executor;
|
||||
public class WifiTetherViewModelTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Mock
|
||||
Application mApplication;
|
||||
@Spy
|
||||
Application mApplication = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
Executor mExecutor;
|
||||
@Mock
|
||||
@@ -57,6 +64,12 @@ public class WifiTetherViewModelTest {
|
||||
MutableLiveData<Integer> mSpeedType;
|
||||
@Mock
|
||||
private MutableLiveData<Boolean> mRestarting;
|
||||
@Mock
|
||||
private SharedConnectivityRepository mSharedConnectivityRepository;
|
||||
@Mock
|
||||
private MutableLiveData<SharedConnectivitySettingsState> mSettingsState;
|
||||
@Mock
|
||||
private MutableLiveData<String> mInstantHotspotSummary;
|
||||
|
||||
WifiTetherViewModel mViewModel;
|
||||
|
||||
@@ -70,8 +83,18 @@ public class WifiTetherViewModelTest {
|
||||
when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
|
||||
when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
|
||||
when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
|
||||
when(featureFactory.getWifiFeatureProvider().getSharedConnectivityRepository())
|
||||
.thenReturn(mSharedConnectivityRepository);
|
||||
when(mSharedConnectivityRepository.isServiceAvailable()).thenReturn(true);
|
||||
when(mSharedConnectivityRepository.getSettingsState()).thenReturn(mSettingsState);
|
||||
|
||||
mViewModel = new WifiTetherViewModel(mApplication);
|
||||
mViewModel.mInstantHotspotSummary = mInstantHotspotSummary;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_observeData() {
|
||||
verify(mSettingsState).observeForever(mViewModel.mInstantHotspotStateObserver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,6 +106,7 @@ public class WifiTetherViewModelTest {
|
||||
|
||||
verify(mSecurityType).removeObserver(mViewModel.mSecurityTypeObserver);
|
||||
verify(mSpeedType).removeObserver(mViewModel.mSpeedTypeObserver);
|
||||
verify(mSettingsState).removeObserver(mViewModel.mInstantHotspotStateObserver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,4 +165,59 @@ public class WifiTetherViewModelTest {
|
||||
public void getRestarting_shouldNotReturnNull() {
|
||||
assertThat(mViewModel.getRestarting()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInstantHotspotFeatureAvailable_serviceAvailable_returnTrue() {
|
||||
when(mSharedConnectivityRepository.isServiceAvailable()).thenReturn(true);
|
||||
|
||||
assertThat(mViewModel.isInstantHotspotFeatureAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInstantHotspotFeatureAvailable_serviceNotAvailable_returnFalse() {
|
||||
when(mSharedConnectivityRepository.isServiceAvailable()).thenReturn(false);
|
||||
|
||||
assertThat(mViewModel.isInstantHotspotFeatureAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstantHotspotSummary_isNotNull() {
|
||||
assertThat(mViewModel.getInstantHotspotSummary()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onInstantHotspotStateChanged_stageNull_summarySetValueNull() {
|
||||
mViewModel.onInstantHotspotStateChanged(null);
|
||||
|
||||
verify(mInstantHotspotSummary).setValue(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onInstantHotspotStateChanged_stateEnabled_summarySetValueOn() {
|
||||
SharedConnectivitySettingsState state = new SharedConnectivitySettingsState.Builder()
|
||||
.setInstantTetherEnabled(true).build();
|
||||
|
||||
mViewModel.onInstantHotspotStateChanged(state);
|
||||
|
||||
verify(mInstantHotspotSummary)
|
||||
.setValue(mApplication.getString(RES_INSTANT_HOTSPOT_SUMMARY_ON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onInstantHotspotStateChanged_stateNotEnabled_recordVisibleSummaryOff() {
|
||||
SharedConnectivitySettingsState state = new SharedConnectivitySettingsState.Builder()
|
||||
.setInstantTetherEnabled(false).build();
|
||||
|
||||
mViewModel.onInstantHotspotStateChanged(state);
|
||||
|
||||
verify(mInstantHotspotSummary)
|
||||
.setValue(mApplication.getString(RES_INSTANT_HOTSPOT_SUMMARY_OFF));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchInstantHotspotSettings_launchSettingsByRepository() {
|
||||
mViewModel.launchInstantHotspotSettings();
|
||||
|
||||
verify(mSharedConnectivityRepository).launchSettings();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user