Merge 24Q4 (ab/12406339) into aosp-main-future
Bug: 370570306 Merged-In: Ie90e7495dd4a134538bae6e3e08eea0d02134b14 Change-Id: I20517e9ee410e95f2cbeb1247c0c0288ed9f006f
This commit is contained in:
@@ -32,7 +32,7 @@ android_test {
|
||||
"truth",
|
||||
"kotlinx_coroutines_test",
|
||||
"Settings-testutils2",
|
||||
"MediaDrmSettingsFlagsLib",
|
||||
"servicestests-utils",
|
||||
// Don't add SettingsLib libraries here - you can use them directly as they are in the
|
||||
// instrumented Settings app.
|
||||
],
|
||||
|
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||
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;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ResetSubscriptionContractTest {
|
||||
|
||||
private static final int SUB_ID_1 = 3;
|
||||
private static final int SUB_ID_2 = 8;
|
||||
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
@Mock
|
||||
private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo1;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo2;
|
||||
|
||||
private Context mContext;
|
||||
private ResetNetworkRequest mRequestArgs;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mRequestArgs = new ResetNetworkRequest(new Bundle());
|
||||
}
|
||||
|
||||
private ResetSubscriptionContract createTestObject() {
|
||||
return new ResetSubscriptionContract(mContext, mRequestArgs) {
|
||||
@Override
|
||||
protected SubscriptionManager getSubscriptionManager() {
|
||||
return mSubscriptionManager;
|
||||
}
|
||||
@Override
|
||||
protected OnSubscriptionsChangedListener getChangeListener() {
|
||||
return mOnSubscriptionsChangedListener;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnyMissingSubscriptionId_returnNull_whenNoSubscriptionChange() {
|
||||
mRequestArgs.setResetTelephonyAndNetworkPolicyManager(SUB_ID_1);
|
||||
doReturn(mSubscriptionInfo1).when(mSubscriptionManager)
|
||||
.getActiveSubscriptionInfo(SUB_ID_1);
|
||||
mRequestArgs.setResetApn(SUB_ID_2);
|
||||
doReturn(mSubscriptionInfo2).when(mSubscriptionManager)
|
||||
.getActiveSubscriptionInfo(SUB_ID_2);
|
||||
|
||||
ResetSubscriptionContract target = createTestObject();
|
||||
|
||||
verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), any());
|
||||
|
||||
assertNull(target.getAnyMissingSubscriptionId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnyMissingSubscriptionId_returnSubId_whenSubscriptionNotActive() {
|
||||
mRequestArgs.setResetTelephonyAndNetworkPolicyManager(SUB_ID_1);
|
||||
doReturn(mSubscriptionInfo1).when(mSubscriptionManager)
|
||||
.getActiveSubscriptionInfo(SUB_ID_1);
|
||||
mRequestArgs.setResetApn(SUB_ID_2);
|
||||
doReturn(null).when(mSubscriptionManager)
|
||||
.getActiveSubscriptionInfo(SUB_ID_2);
|
||||
|
||||
ResetSubscriptionContract target = createTestObject();
|
||||
|
||||
verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), any());
|
||||
|
||||
assertEquals(target.getAnyMissingSubscriptionId(), new Integer(SUB_ID_2));
|
||||
}
|
||||
}
|
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static android.view.flags.Flags.FLAG_ENABLE_VECTOR_CURSOR_A11Y_SETTINGS;
|
||||
|
||||
import static com.android.settings.accessibility.LargePointerIconPreferenceController.OFF;
|
||||
import static com.android.settings.accessibility.LargePointerIconPreferenceController.ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.SwitchPreference;
|
||||
@@ -31,12 +37,16 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LargePointerIconPreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final int UNKNOWN = -1;
|
||||
|
||||
private Context mContext;
|
||||
@@ -51,9 +61,17 @@ public class LargePointerIconPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(FLAG_ENABLE_VECTOR_CURSOR_A11Y_SETTINGS)
|
||||
public void getAvailabilityStatus_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE);
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(FLAG_ENABLE_VECTOR_CURSOR_A11Y_SETTINGS)
|
||||
public void getAvailabilityStatus_shouldReturnConditionallyUnavailable() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -24,7 +26,12 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.provider.Settings;
|
||||
import android.view.accessibility.Flags;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
@@ -33,6 +40,7 @@ import com.android.internal.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -40,6 +48,8 @@ import org.junit.runner.RunWith;
|
||||
public class ReduceBrightColorsPreferenceControllerTest {
|
||||
private static final String PREF_KEY = "rbc_preference";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
private Context mContext;
|
||||
private Resources mResources;;
|
||||
private ReduceBrightColorsPreferenceController mController;
|
||||
@@ -88,6 +98,20 @@ public class ReduceBrightColorsPreferenceControllerTest {
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_A11Y_QS_SHORTCUT)
|
||||
public void getTileComponentName_a11yQsFlagOff_returnComponentName() {
|
||||
assertThat(mController.getTileComponentName())
|
||||
.isEqualTo(REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_A11Y_QS_SHORTCUT)
|
||||
public void getTileComponentName_a11yQsFlagOff_returnNull() {
|
||||
assertThat(mController.getTileComponentName()).isNull();
|
||||
}
|
||||
|
||||
private int resourceId(String type, String name) {
|
||||
return mContext.getResources().getIdentifier(name, type, mContext.getPackageName());
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
include /src/com/android/settings/biometrics/OWNERS
|
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.repository;
|
||||
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_HOME_BUTTON;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UNKNOWN;
|
||||
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FingerprintRepositoryTest {
|
||||
|
||||
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Mock private Resources mResources;
|
||||
@Mock private FingerprintManager mFingerprintManager;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forUnknownSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isFalse();
|
||||
assertThat(repository.canAssumeSfps()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forRearSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_REAR, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isFalse();
|
||||
assertThat(repository.canAssumeSfps()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forUdfpsUltrasonicSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UDFPS_ULTRASONIC, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isTrue();
|
||||
assertThat(repository.canAssumeSfps()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forUdfpsOpticalSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UDFPS_OPTICAL, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isTrue();
|
||||
assertThat(repository.canAssumeSfps()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forPowerButtonSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_POWER_BUTTON, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isFalse();
|
||||
assertThat(repository.canAssumeSfps()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSensorType_forHomeButtonSensor() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_HOME_BUTTON, 1);
|
||||
assertThat(repository.canAssumeUdfps()).isFalse();
|
||||
assertThat(repository.canAssumeSfps()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMaxFingerprints() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 999);
|
||||
assertThat(repository.getMaxFingerprints()).isEqualTo(999);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNumOfEnrolledFingerprintsSize() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 999);
|
||||
setupFingerprintEnrolledFingerprints(mFingerprintManager, 10, 3);
|
||||
setupFingerprintEnrolledFingerprints(mFingerprintManager, 22, 99);
|
||||
|
||||
assertThat(repository.getNumOfEnrolledFingerprintsSize(10)).isEqualTo(3);
|
||||
assertThat(repository.getNumOfEnrolledFingerprintsSize(22)).isEqualTo(99);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMaxFingerprintsInSuw() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 999);
|
||||
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 333);
|
||||
assertThat(repository.getMaxFingerprintsInSuw(mResources))
|
||||
.isEqualTo(333);
|
||||
|
||||
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 20);
|
||||
assertThat(repository.getMaxFingerprintsInSuw(mResources)).isEqualTo(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFirstFingerprintSensorPropertiesInternal() {
|
||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5,
|
||||
new ArrayList<>() /* componentInfo */,
|
||||
TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */);
|
||||
props.add(prop);
|
||||
doAnswer(invocation -> {
|
||||
final IFingerprintAuthenticatorsRegisteredCallback callback =
|
||||
invocation.getArgument(0);
|
||||
callback.onAllAuthenticatorsRegistered(props);
|
||||
return null;
|
||||
}).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
|
||||
|
||||
final FingerprintRepository repository = new FingerprintRepository(mFingerprintManager);
|
||||
assertThat(repository.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnrollStageCount() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 999);
|
||||
|
||||
final int expectedValue = 24;
|
||||
doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
|
||||
|
||||
assertThat(repository.getEnrollStageCount()).isEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnrollStageThreshold() {
|
||||
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||
TYPE_UNKNOWN, 999);
|
||||
|
||||
final float expectedValue0 = 0.42f;
|
||||
final float expectedValue1 = 0.24f;
|
||||
final float expectedValue2 = 0.33f;
|
||||
final float expectedValue3 = 0.90f;
|
||||
doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
|
||||
doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
|
||||
doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
|
||||
doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
|
||||
|
||||
assertThat(repository.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
|
||||
assertThat(repository.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
|
||||
assertThat(repository.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
|
||||
assertThat(repository.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
|
||||
}
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.model
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.os.UserHandle
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.Arrays
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CredentialModelTest {
|
||||
|
||||
private val clock = SystemClock.elapsedRealtimeClock()
|
||||
|
||||
@Test
|
||||
fun testNullBundle() {
|
||||
val credentialModel = CredentialModel(null, clock)
|
||||
Truth.assertThat(credentialModel.userId).isEqualTo(UserHandle.myUserId())
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newCredentialModelIntentExtras(
|
||||
userId: Int, challenge: Long,
|
||||
token: ByteArray?, gkPwHandle: Long
|
||||
): Bundle {
|
||||
val bundle = Bundle()
|
||||
bundle.putInt(Intent.EXTRA_USER_ID, userId)
|
||||
bundle.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge)
|
||||
bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token)
|
||||
bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
|
||||
return bundle
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newValidTokenCredentialIntentExtras(userId: Int): Bundle {
|
||||
return newCredentialModelIntentExtras(
|
||||
userId, 1L, byteArrayOf(0, 1, 2),
|
||||
CredentialModel.INVALID_GK_PW_HANDLE
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newOnlySensorValidCredentialIntentExtras(userId: Int): Bundle {
|
||||
return newCredentialModelIntentExtras(
|
||||
userId, CredentialModel.INVALID_CHALLENGE, null,
|
||||
CredentialModel.INVALID_GK_PW_HANDLE
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newGkPwHandleCredentialIntentExtras(userId: Int, gkPwHandle: Long): Bundle {
|
||||
return newCredentialModelIntentExtras(
|
||||
userId,
|
||||
CredentialModel.INVALID_CHALLENGE,
|
||||
null,
|
||||
gkPwHandle
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkBundleLongValue(
|
||||
bundle1: Bundle, bundle2: Bundle,
|
||||
key: String
|
||||
) {
|
||||
if (!bundle1.containsKey(key)) {
|
||||
return
|
||||
}
|
||||
val value1 = bundle1.getInt(key)
|
||||
val value2 = bundle2.getInt(key)
|
||||
Truth.assertWithMessage(
|
||||
"bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
|
||||
+ value2
|
||||
).that(value1).isEqualTo(value2)
|
||||
}
|
||||
|
||||
private fun checkBundleIntValue(
|
||||
bundle1: Bundle, bundle2: Bundle,
|
||||
key: String
|
||||
) {
|
||||
if (!bundle1.containsKey(key)) {
|
||||
return
|
||||
}
|
||||
val value1 = bundle1.getLong(key)
|
||||
val value2 = bundle2.getLong(key)
|
||||
Truth.assertWithMessage(
|
||||
"bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
|
||||
+ value2
|
||||
).that(value1).isEqualTo(value2)
|
||||
}
|
||||
|
||||
private fun checkBundleByteArrayValue(
|
||||
bundle1: Bundle, bundle2: Bundle,
|
||||
key: String
|
||||
) {
|
||||
if (!bundle1.containsKey(key)) {
|
||||
return
|
||||
}
|
||||
val value1 = bundle1.getByteArray(key)
|
||||
val value2 = bundle2.getByteArray(key)
|
||||
val errMsg = ("bundle not match, key:" + key + ", value1:" + Arrays.toString(value1)
|
||||
+ ", value2:" + Arrays.toString(value2))
|
||||
if (value1 == null) {
|
||||
Truth.assertWithMessage(errMsg).that(value2).isNull()
|
||||
} else {
|
||||
Truth.assertWithMessage(errMsg).that(value1.size).isEqualTo(
|
||||
value2!!.size
|
||||
)
|
||||
for (i in value1.indices) {
|
||||
Truth.assertWithMessage(errMsg).that(value1[i]).isEqualTo(
|
||||
value2[i]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.model
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.biometrics.BiometricEnrollActivity
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class EnrollmentRequestTest {
|
||||
|
||||
private val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
|
||||
@Test
|
||||
fun testIsSuw() {
|
||||
// Default false
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSuw).isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSuw).isFalse()
|
||||
val trueIntent = Intent()
|
||||
trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSuw).isTrue()
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSuw).isFalse()
|
||||
val falseIntent = Intent()
|
||||
trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false)
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, true).isSuw).isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSuw).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAfterSuwOrSuwSuggestedAction() {
|
||||
// Default false
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(Intent(), context, true)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(Intent(), context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val deferredTrueIntent = Intent()
|
||||
deferredTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, true)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(deferredTrueIntent, context, true)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isTrue()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(deferredTrueIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val deferredFalseIntent = Intent()
|
||||
deferredFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, false)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(deferredFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(deferredFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val portalTrueIntent = Intent()
|
||||
portalTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, true)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(portalTrueIntent, context, true)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isTrue()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(portalTrueIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val portalFalseIntent = Intent()
|
||||
portalFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, false)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(portalFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(portalFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val suggestedTrueIntent = Intent()
|
||||
suggestedTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, true)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(suggestedTrueIntent, context, true)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isTrue()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(suggestedTrueIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
val suggestedFalseIntent = Intent()
|
||||
suggestedFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, false)
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(suggestedFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
Truth.assertThat(
|
||||
EnrollmentRequest(suggestedFalseIntent, context, false)
|
||||
.isAfterSuwOrSuwSuggestedAction
|
||||
).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSuwExtras_inSuw() {
|
||||
val suwIntent = Intent()
|
||||
suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
|
||||
val setupRequest = EnrollmentRequest(suwIntent, context, true)
|
||||
val bundle = setupRequest.suwExtras
|
||||
Truth.assertThat(bundle).isNotNull()
|
||||
Truth.assertThat(bundle.size()).isAtLeast(1)
|
||||
Truth.assertThat(bundle.getBoolean(WizardManagerHelper.EXTRA_IS_SETUP_FLOW)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSuwExtras_notInSuw() {
|
||||
val suwIntent = Intent()
|
||||
suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
|
||||
val setupRequest = EnrollmentRequest(suwIntent, context, false)
|
||||
val bundle = setupRequest.suwExtras
|
||||
Truth.assertThat(bundle).isNotNull()
|
||||
Truth.assertThat(bundle.size()).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsSkipIntro() {
|
||||
// Default false
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipIntro).isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipIntro).isFalse()
|
||||
val trueIntent = Intent()
|
||||
trueIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, true)
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipIntro).isTrue()
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipIntro).isTrue()
|
||||
val falseIntent = Intent()
|
||||
falseIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, false)
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsSkipFindSensor() {
|
||||
// Default false
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipFindSensor)
|
||||
.isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipFindSensor)
|
||||
.isFalse()
|
||||
val trueIntent = Intent()
|
||||
trueIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, true)
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipFindSensor).isTrue()
|
||||
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipFindSensor).isTrue()
|
||||
val falseIntent = Intent()
|
||||
falseIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, false)
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
|
||||
.isFalse()
|
||||
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
|
||||
.isFalse()
|
||||
}
|
||||
}
|
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.os.UserHandle
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.internal.widget.VerifyCredentialResponse
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics2.ui.model.CredentialModel
|
||||
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newGkPwHandleCredentialIntentExtras
|
||||
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newOnlySensorValidCredentialIntentExtras
|
||||
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newValidTokenCredentialIntentExtras
|
||||
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator
|
||||
import com.android.settings.password.ChooseLockPattern
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
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.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AutoCredentialViewModelTest {
|
||||
|
||||
@get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock private lateinit var lockPatternUtils: LockPatternUtils
|
||||
|
||||
private var challengeGenerator: TestChallengeGenerator = TestChallengeGenerator()
|
||||
|
||||
private lateinit var viewModel: AutoCredentialViewModel
|
||||
private fun newAutoCredentialViewModel(bundle: Bundle?): AutoCredentialViewModel {
|
||||
return AutoCredentialViewModel(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
lockPatternUtils,
|
||||
challengeGenerator,
|
||||
CredentialModel(bundle, SystemClock.elapsedRealtimeClock())
|
||||
)
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
challengeGenerator = TestChallengeGenerator()
|
||||
}
|
||||
|
||||
private fun setupGenerateChallenge(userId: Int, newSensorId: Int, newChallenge: Long) {
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
challengeGenerator.userId = userId
|
||||
challengeGenerator.sensorId = newSensorId
|
||||
challengeGenerator.challenge = newChallenge
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_validCredentialCase() = runTest {
|
||||
val userId = 99
|
||||
viewModel = newAutoCredentialViewModel(newValidTokenCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.CREDENTIAL_VALID)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_needToChooseLock() = runTest {
|
||||
val userId = 100
|
||||
viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
||||
)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CHOOSE_LOCK)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_needToConfirmLockForSomething() = runTest {
|
||||
val userId = 101
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_needToConfirmLockForNumeric() = runTest {
|
||||
val userId = 102
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|
||||
)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_needToConfirmLockForAlphabetic() = runTest {
|
||||
val userId = 103
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|
||||
)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(this)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_generateChallenge() = runTest {
|
||||
val userId = 104
|
||||
val gkPwHandle = 1111L
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
val newSensorId = 10
|
||||
val newChallenge = 20L
|
||||
setupGenerateChallenge(userId, newSensorId, newChallenge)
|
||||
whenever(
|
||||
lockPatternUtils.verifyGatekeeperPasswordHandle(
|
||||
gkPwHandle,
|
||||
newChallenge,
|
||||
userId
|
||||
)
|
||||
)
|
||||
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
|
||||
val hasCalledRemoveGkPwHandle = AtomicBoolean()
|
||||
Mockito.doAnswer {
|
||||
hasCalledRemoveGkPwHandle.set(true)
|
||||
null
|
||||
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// Check viewModel behavior
|
||||
assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
|
||||
// Check data inside CredentialModel
|
||||
assertThat(viewModel.token).isNotNull()
|
||||
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
|
||||
assertThat(hasCalledRemoveGkPwHandle.get()).isFalse()
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
val generatingChallengeExtras = viewModel.createGeneratingChallengeExtras()
|
||||
assertThat(generatingChallengeExtras).isNotNull()
|
||||
assertThat(generatingChallengeExtras!!.getLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE))
|
||||
.isEqualTo(newChallenge)
|
||||
val tokens =
|
||||
generatingChallengeExtras.getByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
||||
assertThat(tokens).isNotNull()
|
||||
assertThat(tokens!!.size).isEqualTo(1)
|
||||
assertThat(tokens[0]).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckCredential_generateChallengeFail() = runTest {
|
||||
backgroundScope.launch {
|
||||
val userId = 104
|
||||
val gkPwHandle = 1111L
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
val newSensorId = 10
|
||||
val newChallenge = 20L
|
||||
setupGenerateChallenge(userId, newSensorId, newChallenge)
|
||||
whenever(
|
||||
lockPatternUtils.verifyGatekeeperPasswordHandle(
|
||||
gkPwHandle,
|
||||
newChallenge,
|
||||
userId
|
||||
)
|
||||
)
|
||||
.thenReturn(newBadCredential(0))
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run credential check
|
||||
val action = viewModel.checkCredential(this)
|
||||
runCurrent()
|
||||
|
||||
assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
|
||||
assertThat(generateFails.size).isEqualTo(1)
|
||||
assertThat(generateFails[0]).isEqualTo(true)
|
||||
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
|
||||
|
||||
// Check createGeneratingChallengeExtras()
|
||||
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetUserId_fromIntent() {
|
||||
val userId = 106
|
||||
viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
|
||||
// Get userId
|
||||
assertThat(viewModel.userId).isEqualTo(userId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_invalidChooseLock() = runTest {
|
||||
backgroundScope.launch {
|
||||
val userId = 107
|
||||
val gkPwHandle = 3333L
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
|
||||
val intent = Intent()
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
true,
|
||||
ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isFalse()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_invalidConfirmLock() = runTest {
|
||||
backgroundScope.launch {
|
||||
val userId = 107
|
||||
val gkPwHandle = 3333L
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
|
||||
val intent = Intent()
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
false,
|
||||
ActivityResult(Activity.RESULT_OK + 1, intent),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isFalse()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_nullDataChooseLock() = runTest {
|
||||
val userId = 108
|
||||
val gkPwHandle = 4444L
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
true,
|
||||
ActivityResult(ChooseLockPattern.RESULT_FINISHED, null),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isFalse()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_nullDataConfirmLock() = runTest {
|
||||
val userId = 109
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
false,
|
||||
ActivityResult(Activity.RESULT_OK, null),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isFalse()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_validChooseLock() = runTest {
|
||||
val userId = 108
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
val gkPwHandle = 6666L
|
||||
val newSensorId = 50
|
||||
val newChallenge = 60L
|
||||
setupGenerateChallenge(userId, newSensorId, newChallenge)
|
||||
whenever(
|
||||
lockPatternUtils.verifyGatekeeperPasswordHandle(
|
||||
gkPwHandle,
|
||||
newChallenge,
|
||||
userId
|
||||
)
|
||||
)
|
||||
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
|
||||
val hasCalledRemoveGkPwHandle = AtomicBoolean()
|
||||
Mockito.doAnswer {
|
||||
hasCalledRemoveGkPwHandle.set(true)
|
||||
null
|
||||
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val intent =
|
||||
Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
true,
|
||||
ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isTrue()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
assertThat(viewModel.token).isNotNull()
|
||||
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
|
||||
assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGenerateChallengeAsCredentialActivityResult_validConfirmLock() = runTest {
|
||||
val userId = 109
|
||||
viewModel =
|
||||
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
|
||||
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
|
||||
)
|
||||
val gkPwHandle = 5555L
|
||||
val newSensorId = 80
|
||||
val newChallenge = 90L
|
||||
setupGenerateChallenge(userId, newSensorId, newChallenge)
|
||||
whenever(
|
||||
lockPatternUtils.verifyGatekeeperPasswordHandle(
|
||||
gkPwHandle,
|
||||
newChallenge,
|
||||
userId
|
||||
)
|
||||
)
|
||||
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
|
||||
val hasCalledRemoveGkPwHandle = AtomicBoolean()
|
||||
Mockito.doAnswer {
|
||||
hasCalledRemoveGkPwHandle.set(true)
|
||||
null
|
||||
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
|
||||
|
||||
val generateFails = listOfGenerateChallengeFailedFlow()
|
||||
|
||||
// Run generateChallengeAsCredentialActivityResult()
|
||||
val intent =
|
||||
Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
|
||||
val ret = viewModel.generateChallengeAsCredentialActivityResult(
|
||||
false,
|
||||
ActivityResult(Activity.RESULT_OK, intent),
|
||||
backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(ret).isTrue()
|
||||
assertThat(generateFails.size).isEqualTo(0)
|
||||
assertThat(viewModel.token).isNotNull()
|
||||
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
|
||||
assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
|
||||
}
|
||||
|
||||
private fun TestScope.listOfGenerateChallengeFailedFlow(): List<Boolean> =
|
||||
mutableListOf<Boolean>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.generateChallengeFailedFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
class TestChallengeGenerator : ChallengeGenerator {
|
||||
var sensorId = -1
|
||||
var userId = UserHandle.myUserId()
|
||||
var challenge = CredentialModel.INVALID_CHALLENGE
|
||||
var callbackRunCount = 0
|
||||
|
||||
override var callback: AutoCredentialViewModel.GenerateChallengeCallback? = null
|
||||
|
||||
override fun generateChallenge(userId: Int) {
|
||||
callback?.let {
|
||||
it.onChallengeGenerated(sensorId, this.userId, challenge)
|
||||
++callbackRunCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun newGoodCredential(gkPwHandle: Long, hat: ByteArray): VerifyCredentialResponse {
|
||||
return VerifyCredentialResponse.Builder()
|
||||
.setGatekeeperPasswordHandle(gkPwHandle)
|
||||
.setGatekeeperHAT(hat)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun newBadCredential(timeout: Int): VerifyCredentialResponse {
|
||||
return if (timeout > 0) {
|
||||
VerifyCredentialResponse.fromTimeout(timeout)
|
||||
} else {
|
||||
VerifyCredentialResponse.fromError()
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics2.ui.viewmodel;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DeviceFoldedViewModelTest {
|
||||
|
||||
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
private DeviceFoldedViewModel mViewModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final Application application = ApplicationProvider.getApplicationContext();
|
||||
mViewModel = new DeviceFoldedViewModel(new ScreenSizeFoldProvider(application),
|
||||
application.getMainExecutor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLiveData() {
|
||||
final Configuration config1 = new Configuration();
|
||||
config1.smallestScreenWidthDp = 601;
|
||||
mViewModel.onConfigurationChanged(config1);
|
||||
assertThat(mViewModel.getLiveData().getValue()).isFalse();
|
||||
|
||||
final Configuration config2 = new Configuration();
|
||||
config2.smallestScreenWidthDp = 599;
|
||||
mViewModel.onConfigurationChanged(config2);
|
||||
assertThat(mViewModel.getLiveData().getValue()).isTrue();
|
||||
}
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics2.ui.viewmodel;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Application;
|
||||
import android.view.Surface;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DeviceRotationViewModelTest {
|
||||
|
||||
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
private TestDeviceRotationViewModel mViewModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
TestDeviceRotationViewModel.sTestRotation = 3;
|
||||
mViewModel = new TestDeviceRotationViewModel(ApplicationProvider.getApplicationContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultLiveDataNotNull() {
|
||||
assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDisplayChange() {
|
||||
mViewModel.sTestRotation = 3;
|
||||
mViewModel.triggerOnDisplayChanged();
|
||||
assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
|
||||
}
|
||||
|
||||
public static class TestDeviceRotationViewModel extends DeviceRotationViewModel {
|
||||
|
||||
@Surface.Rotation static int sTestRotation = 0;
|
||||
|
||||
public TestDeviceRotationViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
}
|
||||
|
||||
void triggerOnDisplayChanged() {
|
||||
mDisplayListener.onDisplayChanged(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRotation() {
|
||||
return sTestRotation;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel;
|
||||
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP;
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
import android.app.Application;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FingerprintEnrollEnrollingViewModelTest {
|
||||
|
||||
private static final int TEST_USER_ID = 33;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
@Rule
|
||||
public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
@Mock
|
||||
private FingerprintManager mFingerprintManager;
|
||||
|
||||
private Application mApplication;
|
||||
private FingerprintEnrollEnrollingViewModel mViewModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mApplication = ApplicationProvider.getApplicationContext();
|
||||
mViewModel = new FingerprintEnrollEnrollingViewModel(
|
||||
mApplication,
|
||||
TEST_USER_ID,
|
||||
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIconTouchDialog() {
|
||||
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(null);
|
||||
|
||||
mViewModel.showIconTouchDialog();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tesBackPressedScenario() {
|
||||
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(null);
|
||||
assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
|
||||
|
||||
mViewModel.setOnBackPressed();
|
||||
assertThat(mViewModel.getOnBackPressed()).isEqualTo(true);
|
||||
|
||||
mViewModel.onCancelledDueToOnBackPressed();
|
||||
assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipPressedScenario() {
|
||||
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(null);
|
||||
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
|
||||
|
||||
mViewModel.setOnSkipPressed();
|
||||
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(true);
|
||||
|
||||
mViewModel.onCancelledDueToOnSkipPressed();
|
||||
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFirstFingerprintSensorPropertiesInternal() {
|
||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5,
|
||||
new ArrayList<>() /* componentInfo */,
|
||||
TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */);
|
||||
props.add(prop);
|
||||
doAnswer(invocation -> {
|
||||
final IFingerprintAuthenticatorsRegisteredCallback callback =
|
||||
invocation.getArgument(0);
|
||||
callback.onAllAuthenticatorsRegistered(props);
|
||||
return null;
|
||||
}).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
|
||||
|
||||
mViewModel = new FingerprintEnrollEnrollingViewModel(
|
||||
mApplication,
|
||||
TEST_USER_ID,
|
||||
new FingerprintRepository(mFingerprintManager)
|
||||
);
|
||||
|
||||
assertThat(mViewModel.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnrollStageCount() {
|
||||
final int expectedValue = 24;
|
||||
doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
|
||||
|
||||
assertThat(mViewModel.getEnrollStageCount()).isEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnrollStageThreshold() {
|
||||
final float expectedValue0 = 0.42f;
|
||||
final float expectedValue1 = 0.24f;
|
||||
final float expectedValue2 = 0.33f;
|
||||
final float expectedValue3 = 0.90f;
|
||||
|
||||
doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
|
||||
doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
|
||||
doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
|
||||
doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
|
||||
|
||||
assertThat(mViewModel.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
|
||||
assertThat(mViewModel.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
|
||||
assertThat(mViewModel.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
|
||||
assertThat(mViewModel.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
|
||||
}
|
||||
}
|
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FingerprintEnrollErrorDialogViewModelTest {
|
||||
|
||||
private val application = ApplicationProvider.getApplicationContext<Application>()
|
||||
private var viewModel: FingerprintEnrollErrorDialogViewModel =
|
||||
FingerprintEnrollErrorDialogViewModel(application, false)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
// Make sure viewModel is new for each test
|
||||
viewModel = FingerprintEnrollErrorDialogViewModel(application, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsDialogNotShownDefaultFalse() {
|
||||
assertThat(viewModel.isDialogShown).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsSuw() {
|
||||
assertThat(FingerprintEnrollErrorDialogViewModel(application, false).isSuw).isFalse()
|
||||
assertThat(FingerprintEnrollErrorDialogViewModel(application, true).isSuw).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNewDialog() = runTest {
|
||||
val newDialogs: List<Int> = mutableListOf<Int>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.newDialogFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
runCurrent()
|
||||
|
||||
// Default values
|
||||
assertThat(viewModel.isDialogShown).isFalse()
|
||||
assertThat(newDialogs.size).isEqualTo(0)
|
||||
|
||||
val testErrorMsgId = 3456
|
||||
viewModel.newDialog(testErrorMsgId)
|
||||
runCurrent()
|
||||
|
||||
// verify after emit
|
||||
assertThat(viewModel.isDialogShown).isTrue()
|
||||
assertThat(newDialogs.size).isEqualTo(1)
|
||||
assertThat(newDialogs[0]).isEqualTo(testErrorMsgId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTriggerRetry() = runTest {
|
||||
val triggerRetries: List<Any> = mutableListOf<Any>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.triggerRetryFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
runCurrent()
|
||||
|
||||
// Default values
|
||||
assertThat(triggerRetries.size).isEqualTo(0)
|
||||
|
||||
viewModel.triggerRetry()
|
||||
runCurrent()
|
||||
|
||||
// verify after emit
|
||||
assertThat(triggerRetries.size).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetResultFinish() = runTest {
|
||||
val setResults: List<FingerprintErrorDialogSetResultAction> =
|
||||
mutableListOf<FingerprintErrorDialogSetResultAction>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.setResultFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
runCurrent()
|
||||
|
||||
// Default values
|
||||
assertThat(setResults.size).isEqualTo(0)
|
||||
|
||||
viewModel.setResultAndFinish(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
|
||||
runCurrent()
|
||||
|
||||
// verify after emit
|
||||
assertThat(setResults.size).isEqualTo(1)
|
||||
assertThat(setResults[0]).isEqualTo(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
|
||||
}
|
||||
}
|
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel;
|
||||
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG;
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP;
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FingerprintEnrollFindSensorViewModelTest {
|
||||
|
||||
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
private Application mApplication;
|
||||
private FingerprintEnrollFindSensorViewModel mViewModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mApplication = ApplicationProvider.getApplicationContext();
|
||||
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickSkipButtonNotInSuw() {
|
||||
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
|
||||
mViewModel.onSkipButtonClick();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickSkipButtonInSuw() {
|
||||
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, true);
|
||||
mViewModel.onSkipButtonClick();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickSkipDialogButton() {
|
||||
mViewModel.onSkipDialogButtonClick();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickStartDialogButton() {
|
||||
mViewModel.onStartButtonClick();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearActionLiveData() {
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
|
||||
|
||||
mViewModel.onStartButtonClick();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isNotNull();
|
||||
|
||||
mViewModel.clearActionLiveData();
|
||||
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
|
||||
}
|
||||
}
|
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel;
|
||||
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK;
|
||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK;
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
|
||||
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FingerprintEnrollFinishViewModelTest {
|
||||
|
||||
private static final int USER_ID = 334;
|
||||
private static final int MAX_ENROLLABLE = 5;
|
||||
|
||||
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
@Mock private FingerprintManager mFingerprintManager;
|
||||
|
||||
private Application mApplication;
|
||||
private EnrollmentRequest mRequest;
|
||||
private FingerprintEnrollFinishViewModel mViewModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mApplication = ApplicationProvider.getApplicationContext();
|
||||
mRequest = new EnrollmentRequest(new Intent(), mApplication, true);
|
||||
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
|
||||
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAssumeSfps() {
|
||||
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
|
||||
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
|
||||
assertThat(mViewModel.canAssumeSfps()).isFalse();
|
||||
|
||||
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
|
||||
newFingerprintRepository(mFingerprintManager, TYPE_REAR, MAX_ENROLLABLE));
|
||||
assertThat(mViewModel.canAssumeSfps()).isFalse();
|
||||
|
||||
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
|
||||
newFingerprintRepository(mFingerprintManager, TYPE_POWER_BUTTON, MAX_ENROLLABLE));
|
||||
assertThat(mViewModel.canAssumeSfps()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAnotherFingerprintEnrollable() {
|
||||
setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE);
|
||||
assertThat(mViewModel.isAnotherFingerprintEnrollable()).isFalse();
|
||||
|
||||
setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE - 1);
|
||||
assertThat(mViewModel.isAnotherFingerprintEnrollable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRequest() {
|
||||
assertThat(mViewModel.getRequest()).isEqualTo(mRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAddButtonClick() {
|
||||
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
|
||||
|
||||
// Test init value
|
||||
assertThat(actionLiveData.getValue()).isNull();
|
||||
|
||||
// Test onAddButtonClick()
|
||||
mViewModel.onAddButtonClick();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK);
|
||||
|
||||
// Clear
|
||||
mViewModel.clearActionLiveData();
|
||||
assertThat(actionLiveData.getValue()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnNextButtonClick() {
|
||||
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
|
||||
|
||||
// Test init value
|
||||
assertThat(actionLiveData.getValue()).isNull();
|
||||
|
||||
// Test onNextButtonClick()
|
||||
mViewModel.onNextButtonClick();
|
||||
assertThat(actionLiveData.getValue()).isEqualTo(
|
||||
FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK);
|
||||
|
||||
// Clear
|
||||
mViewModel.clearActionLiveData();
|
||||
assertThat(actionLiveData.getValue()).isNull();
|
||||
}
|
||||
}
|
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import android.content.res.Resources
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository
|
||||
import com.android.settings.biometrics2.ui.model.EnrollmentRequest
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.CONTINUE_ENROLL
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.DONE_AND_FINISH
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.SKIP_OR_CANCEL
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwDeferredRequest
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwPortalRequest
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwSuggestedActionFlowRequest
|
||||
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
|
||||
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
|
||||
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
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.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FingerprintEnrollIntroViewModelTest {
|
||||
|
||||
@get:Rule val mockito = MockitoJUnit.rule()
|
||||
|
||||
@Mock private lateinit var resources: Resources
|
||||
@Mock private lateinit var fingerprintManager: FingerprintManager
|
||||
|
||||
private var application: Application = ApplicationProvider.getApplicationContext()
|
||||
|
||||
private fun newFingerprintEnrollIntroViewModel(
|
||||
fingerprintRepository: FingerprintRepository,
|
||||
enrollmentRequest: EnrollmentRequest
|
||||
) = FingerprintEnrollIntroViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
enrollmentRequest,
|
||||
TEST_USER_ID
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
application = ApplicationProvider.getApplicationContext()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPageStatusFlowDefaultAndUpdate() = runTest {
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 1),
|
||||
newAllFalseRequest(application)
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
// assert default values
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].hasScrollToBottom()).isFalse()
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
|
||||
viewModel.updateEnrollableStatus(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
// assert new updated value
|
||||
assertThat(statusList.size).isEqualTo(2)
|
||||
assertThat(statusList[1].hasScrollToBottom()).isFalse()
|
||||
assertThat(statusList[1].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
}
|
||||
|
||||
fun testOnStartToUpdateEnrollableStatusOk_isSuw() = runTest {
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
|
||||
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newIsSuwRequest(application)
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusReachMax_isSuw() = runTest {
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
|
||||
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newIsSuwRequest(application)
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusOk_isNotSuw() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusOk(newAllFalseRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusReachMax_isNotSuw() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusReachMax(newAllFalseRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusOk_isSuwDeferred() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusOk(newIsSuwDeferredRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwDeferred() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusReachMax(newIsSuwDeferredRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusOk_isSuwPortal() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusOk(newIsSuwPortalRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwPortal() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusReachMax(newIsSuwPortalRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusOk_isSuwSuggestedActionFlow() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusOk(newIsSuwSuggestedActionFlowRequest(application))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwSuggestedActionFlow() = runTest {
|
||||
testOnStartToUpdateEnrollableStatusReachMax(
|
||||
newIsSuwSuggestedActionFlowRequest(application)
|
||||
)
|
||||
}
|
||||
|
||||
private fun TestScope.testOnStartToUpdateEnrollableStatusOk(request: EnrollmentRequest) {
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
request
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
|
||||
}
|
||||
|
||||
private fun TestScope.testOnStartToUpdateEnrollableStatusReachMax(request: EnrollmentRequest) {
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 5)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
request
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsParentalConsentRequired() {
|
||||
// We shall not mock FingerprintRepository, but
|
||||
// FingerprintRepository.isParentalConsentRequired() calls static method inside, we can't
|
||||
// mock static method
|
||||
val fingerprintRepository = Mockito.mock(
|
||||
FingerprintRepository::class.java
|
||||
)
|
||||
val viewModel = FingerprintEnrollIntroViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
newAllFalseRequest(application),
|
||||
TEST_USER_ID
|
||||
)
|
||||
Mockito.`when`(
|
||||
fingerprintRepository.isParentalConsentRequired(application)
|
||||
).thenReturn(true)
|
||||
assertThat(viewModel.isParentalConsentRequired).isEqualTo(true)
|
||||
Mockito.`when`(
|
||||
fingerprintRepository.isParentalConsentRequired(application)
|
||||
).thenReturn(false)
|
||||
assertThat(viewModel.isParentalConsentRequired).isEqualTo(false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsBiometricUnlockDisabledByAdmin() {
|
||||
// We shall not mock FingerprintRepository, but
|
||||
// FingerprintRepository.isDisabledByAdmin() calls static method inside, we can't mock
|
||||
// static method
|
||||
val fingerprintRepository = Mockito.mock(FingerprintRepository::class.java)
|
||||
val viewModel = FingerprintEnrollIntroViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
newAllFalseRequest(application),
|
||||
TEST_USER_ID
|
||||
)
|
||||
Mockito.`when`(
|
||||
fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
|
||||
).thenReturn(true)
|
||||
assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(true)
|
||||
Mockito.`when`(
|
||||
fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
|
||||
).thenReturn(false)
|
||||
assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetHasScrolledToBottom() = runTest {
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newAllFalseRequest(application)
|
||||
)
|
||||
|
||||
val pageStatusList = listOfPageStatusFlow(viewModel)
|
||||
|
||||
viewModel.setHasScrolledToBottom(true, backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
assertThat(pageStatusList[pageStatusList.size-1].hasScrollToBottom()).isEqualTo(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnNextButtonClick_enrollNext() = runTest {
|
||||
// Set latest status to FINGERPRINT_ENROLLABLE_OK
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
|
||||
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newIsSuwRequest(application)
|
||||
)
|
||||
|
||||
val actions = listOfActionFlow(viewModel)
|
||||
|
||||
// Perform click on `next`
|
||||
viewModel.onNextButtonClick(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
assertThat(actions.size).isEqualTo(1)
|
||||
assertThat(actions[0]).isEqualTo(CONTINUE_ENROLL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnNextButtonClick_doneAndFinish() = runTest {
|
||||
// Set latest status to FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
|
||||
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newIsSuwRequest(application)
|
||||
)
|
||||
|
||||
val statusList = listOfPageStatusFlow(viewModel)
|
||||
val actionList = listOfActionFlow(viewModel)
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(statusList.size).isEqualTo(1)
|
||||
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
|
||||
val actions = listOfActionFlow(viewModel)
|
||||
|
||||
// Perform click on `next`
|
||||
viewModel.onNextButtonClick(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
assertThat(actionList.size).isEqualTo(1)
|
||||
assertThat(actionList[0]).isEqualTo(DONE_AND_FINISH)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnSkipOrCancelButtonClick() = runTest {
|
||||
val viewModel = newFingerprintEnrollIntroViewModel(
|
||||
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
|
||||
newAllFalseRequest(application)
|
||||
)
|
||||
|
||||
val actions = listOfActionFlow(viewModel)
|
||||
|
||||
viewModel.onSkipOrCancelButtonClick(backgroundScope)
|
||||
runCurrent()
|
||||
|
||||
assertThat(actions.size).isEqualTo(1)
|
||||
assertThat(actions[0]).isEqualTo(SKIP_OR_CANCEL)
|
||||
}
|
||||
|
||||
private fun TestScope.listOfActionFlow(
|
||||
viewModel: FingerprintEnrollIntroViewModel
|
||||
): List<FingerprintEnrollIntroAction> =
|
||||
mutableListOf<FingerprintEnrollIntroAction>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.actionFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.listOfPageStatusFlow(
|
||||
viewModel: FingerprintEnrollIntroViewModel
|
||||
): List<FingerprintEnrollIntroStatus> =
|
||||
mutableListOf<FingerprintEnrollIntroStatus>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.pageStatusFlow.toList(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TEST_USER_ID = 33
|
||||
}
|
||||
}
|
@@ -1,421 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel;
|
||||
|
||||
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
|
||||
import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR;
|
||||
import static android.hardware.fingerprint.FingerprintManager.EnrollReason;
|
||||
import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
|
||||
|
||||
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.only;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.res.Resources;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
|
||||
import com.android.settings.biometrics.fingerprint.MessageDisplayController;
|
||||
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
||||
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
|
||||
import com.android.settings.testutils.InstantTaskExecutorRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FingerprintEnrollProgressViewModelTest {
|
||||
|
||||
private static final int TEST_USER_ID = 334;
|
||||
|
||||
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
|
||||
|
||||
@Mock private Application mApplication;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private FingerprintUpdater mFingerprintUpdater;
|
||||
|
||||
private FingerprintEnrollProgressViewModel mViewModel;
|
||||
private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>();
|
||||
private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>();
|
||||
private int mEnrollmentMessageDisplayControllerFlagResId;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mEnrollmentMessageDisplayControllerFlagResId = ApplicationProvider.getApplicationContext()
|
||||
.getResources().getIdentifier("enrollment_message_display_controller_flag", "bool",
|
||||
SETTINGS_PACKAGE_NAME);
|
||||
|
||||
when(mApplication.getResources()).thenReturn(mResources);
|
||||
|
||||
// Not use MessageDisplayController by default
|
||||
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(false);
|
||||
mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater,
|
||||
TEST_USER_ID);
|
||||
|
||||
mCancellationSignalWrapper.mValue = null;
|
||||
mCallbackWrapper.mValue = null;
|
||||
doAnswer(invocation -> {
|
||||
mCancellationSignalWrapper.mValue = invocation.getArgument(1);
|
||||
mCallbackWrapper.mValue = invocation.getArgument(3);
|
||||
return null;
|
||||
}).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
|
||||
eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartFindSensor() {
|
||||
@EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
|
||||
final byte[] token = new byte[] { 1, 2, 3 };
|
||||
mViewModel.setToken(token);
|
||||
|
||||
// Start enrollment
|
||||
final Object ret = mViewModel.startEnrollment(enrollReason);
|
||||
|
||||
assertThat(ret).isNotNull();
|
||||
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
|
||||
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
|
||||
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartEnrolling() {
|
||||
@EnrollReason final int enrollReason = ENROLL_ENROLL;
|
||||
final byte[] token = new byte[] { 1, 2, 3 };
|
||||
mViewModel.setToken(token);
|
||||
|
||||
// Start enrollment
|
||||
final Object ret = mViewModel.startEnrollment(enrollReason);
|
||||
|
||||
assertThat(ret).isNotNull();
|
||||
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
|
||||
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
|
||||
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartEnrollingWithMessageDisplayController() {
|
||||
// Enable MessageDisplayController and mock handler for it
|
||||
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
|
||||
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
|
||||
|
||||
@EnrollReason final int enrollReason = ENROLL_ENROLL;
|
||||
final byte[] token = new byte[] { 1, 2, 3 };
|
||||
mViewModel.setToken(token);
|
||||
|
||||
// Start enrollment
|
||||
final Object ret = mViewModel.startEnrollment(enrollReason);
|
||||
|
||||
assertThat(ret).isNotNull();
|
||||
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
|
||||
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isTrue();
|
||||
final EnrollmentCallback callback1 = mCallbackWrapper.mValue;
|
||||
|
||||
// Cancel and start again
|
||||
mViewModel.cancelEnrollment();
|
||||
mViewModel.startEnrollment(enrollReason);
|
||||
|
||||
// Shall not use the same MessageDisplayController
|
||||
verify(mFingerprintUpdater, times(2)).enroll(eq(token), any(CancellationSignal.class),
|
||||
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
assertThat(callback1).isNotEqualTo(mCallbackWrapper.mValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartEnrollmentFailBecauseOfNoToken() {
|
||||
// Start enrollment
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);
|
||||
|
||||
assertThat(ret).isNull();
|
||||
verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
|
||||
any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt(),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelEnrollment() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCancellationSignalWrapper.mValue).isNotNull();
|
||||
|
||||
// Cancel enrollment
|
||||
mViewModel.cancelEnrollment();
|
||||
|
||||
assertThat(mCancellationSignalWrapper.mValue.isCanceled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressUpdate() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Test default value
|
||||
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
|
||||
EnrollmentProgress progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(-1);
|
||||
assertThat(progress.getRemaining()).isEqualTo(0);
|
||||
|
||||
// Update first progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(25);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(25);
|
||||
|
||||
// Update second progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(20);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(20);
|
||||
|
||||
// Update latest progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(0);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressUpdateClearHelpMessage() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
|
||||
final LiveData<EnrollmentStatusMessage> helpMsgLiveData =
|
||||
mViewModel.getHelpMessageLiveData();
|
||||
|
||||
// Update first progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(25);
|
||||
EnrollmentProgress progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(25);
|
||||
|
||||
// Update help message
|
||||
final int testHelpMsgId = 3;
|
||||
final String testHelpString = "Test Help String";
|
||||
mCallbackWrapper.mValue.onEnrollmentHelp(testHelpMsgId, testHelpString);
|
||||
final EnrollmentStatusMessage helpMsg = helpMsgLiveData.getValue();
|
||||
assertThat(helpMsg).isNotNull();
|
||||
assertThat(helpMsg.getMsgId()).isEqualTo(testHelpMsgId);
|
||||
assertThat(helpMsg.getStr().toString()).isEqualTo(testHelpString);
|
||||
|
||||
// Update second progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(20);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(20);
|
||||
|
||||
// Help message shall be set to null
|
||||
assertThat(helpMsgLiveData.getValue()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressUpdateWithMessageDisplayController() {
|
||||
// Enable MessageDisplayController and mock handler for it
|
||||
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
|
||||
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
|
||||
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
|
||||
// Start enrollment
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Test default value
|
||||
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
|
||||
EnrollmentProgress progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(-1);
|
||||
assertThat(progress.getRemaining()).isEqualTo(0);
|
||||
|
||||
// Update first progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(25);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(25);
|
||||
|
||||
// Update second progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(20);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(20);
|
||||
|
||||
// Update latest progress
|
||||
mCallbackWrapper.mValue.onEnrollmentProgress(0);
|
||||
progress = progressLiveData.getValue();
|
||||
assertThat(progress).isNotNull();
|
||||
assertThat(progress.getSteps()).isEqualTo(25);
|
||||
assertThat(progress.getRemaining()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetErrorMessageLiveData() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Check default value
|
||||
final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getErrorMessageLiveData();
|
||||
assertThat(liveData.getValue()).isNull();
|
||||
|
||||
// Notify error message
|
||||
final int errMsgId = 3;
|
||||
final String errMsg = "test error message";
|
||||
mCallbackWrapper.mValue.onEnrollmentError(errMsgId, errMsg);
|
||||
final EnrollmentStatusMessage value = liveData.getValue();
|
||||
assertThat(value).isNotNull();
|
||||
assertThat(value.getMsgId()).isEqualTo(errMsgId);
|
||||
assertThat(value.getStr().toString()).isEqualTo(errMsg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHelpMessageLiveData() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Check default value
|
||||
final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getHelpMessageLiveData();
|
||||
assertThat(liveData.getValue()).isNull();
|
||||
|
||||
// Notify help message
|
||||
final int errMsgId = 3;
|
||||
final String errMsg = "test error message";
|
||||
mCallbackWrapper.mValue.onEnrollmentHelp(errMsgId, errMsg);
|
||||
final EnrollmentStatusMessage value = liveData.getValue();
|
||||
assertThat(value).isNotNull();
|
||||
assertThat(value.getMsgId()).isEqualTo(errMsgId);
|
||||
assertThat(value.getStr().toString()).isEqualTo(errMsg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAcquireLiveData() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Check default value
|
||||
final LiveData<Boolean> liveData = mViewModel.getAcquireLiveData();
|
||||
assertThat(liveData.getValue()).isNull();
|
||||
|
||||
// Notify acquire message
|
||||
mCallbackWrapper.mValue.onAcquired(true);
|
||||
assertThat(liveData.getValue()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPointerDownLiveData() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Check default value
|
||||
final LiveData<Integer> liveData = mViewModel.getPointerDownLiveData();
|
||||
assertThat(liveData.getValue()).isNull();
|
||||
|
||||
// Notify acquire message
|
||||
final int value = 33;
|
||||
mCallbackWrapper.mValue.onUdfpsPointerDown(value);
|
||||
assertThat(liveData.getValue()).isEqualTo(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPointerUpLiveData() {
|
||||
// Start enrollment
|
||||
mViewModel.setToken(new byte[] { 1, 2, 3 });
|
||||
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
|
||||
assertThat(ret).isNotNull();
|
||||
assertThat(mCallbackWrapper.mValue).isNotNull();
|
||||
|
||||
// Check default value
|
||||
final LiveData<Integer> liveData = mViewModel.getPointerUpLiveData();
|
||||
assertThat(liveData.getValue()).isNull();
|
||||
|
||||
// Notify acquire message
|
||||
final int value = 44;
|
||||
mCallbackWrapper.mValue.onUdfpsPointerUp(value);
|
||||
assertThat(liveData.getValue()).isEqualTo(value);
|
||||
}
|
||||
|
||||
private static class TestWrapper<T> {
|
||||
T mValue;
|
||||
}
|
||||
|
||||
private static class TestHandler extends Handler {
|
||||
|
||||
TestHandler() {
|
||||
super(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
|
||||
msg.getCallback().run();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.os.Bundle
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
|
||||
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
|
||||
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
|
||||
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
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.Mock
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FingerprintEnrollmentViewModelTest {
|
||||
|
||||
@get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
private val application: Application
|
||||
get() = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Mock
|
||||
private lateinit var fingerprintManager: FingerprintManager
|
||||
|
||||
private lateinit var fingerprintRepository: FingerprintRepository
|
||||
private lateinit var viewModel: FingerprintEnrollmentViewModel
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
fingerprintRepository = newFingerprintRepository(
|
||||
fingerprintManager,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
5
|
||||
)
|
||||
viewModel = FingerprintEnrollmentViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
newAllFalseRequest(application)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetRequest() {
|
||||
assertThat(viewModel.request).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsWaitingActivityResultDefaultFalse() {
|
||||
assertThat(viewModel.isWaitingActivityResult.value).isFalse()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallKeepNullIntent_woChallengeExtra() {
|
||||
val retResult = viewModel.getOverrideActivityResult(
|
||||
ActivityResult(22, null), null
|
||||
)
|
||||
assertThat(retResult).isNotNull()
|
||||
assertThat(retResult.data).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallKeepNullIntent_noIntent_woChallengeExtra() {
|
||||
val intent = Intent()
|
||||
val retResult = viewModel.getOverrideActivityResult(
|
||||
ActivityResult(33, intent), null
|
||||
)
|
||||
assertThat(retResult).isNotNull()
|
||||
assertThat(retResult.data).isEqualTo(intent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallKeepNull_woAdded_woIntent_withChallenge() {
|
||||
val extra = Bundle()
|
||||
extra.putString("test1", "test123")
|
||||
|
||||
val retResult = viewModel.getOverrideActivityResult(
|
||||
ActivityResult(33, null), extra
|
||||
)
|
||||
|
||||
assertThat(retResult).isNotNull()
|
||||
assertThat(retResult.data).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallCreateNew_woIntent_withChallenge() {
|
||||
val key1 = "test1"
|
||||
val key2 = "test2"
|
||||
val extra = Bundle().apply {
|
||||
putString(key1, "test123")
|
||||
putInt(key2, 9999)
|
||||
}
|
||||
|
||||
viewModel.isNewFingerprintAdded = true
|
||||
|
||||
val retResult = viewModel.getOverrideActivityResult(
|
||||
ActivityResult(33, null), extra
|
||||
)
|
||||
assertThat(retResult).isNotNull()
|
||||
|
||||
val retIntent = retResult.data
|
||||
assertThat(retIntent).isNotNull()
|
||||
|
||||
val retExtra = retIntent!!.extras
|
||||
assertThat(retExtra).isNotNull()
|
||||
assertThat(retExtra!!.size).isEqualTo(extra.size)
|
||||
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
|
||||
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallNotMerge_nonAdded_woIntent_withChallenge() {
|
||||
val extra = Bundle().apply {
|
||||
putString("test2", "test123")
|
||||
}
|
||||
|
||||
val key2 = "test2"
|
||||
val intent = Intent().apply {
|
||||
putExtra(key2, 3456L)
|
||||
}
|
||||
|
||||
val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
|
||||
|
||||
assertThat(retResult).isNotNull()
|
||||
|
||||
val retIntent = retResult.data
|
||||
assertThat(retIntent).isNotNull()
|
||||
|
||||
val retExtra = retIntent!!.extras
|
||||
assertThat(retExtra).isNotNull()
|
||||
assertThat(retExtra!!.size).isEqualTo(intent.extras!!.size)
|
||||
assertThat(retExtra.getString(key2)).isEqualTo(intent.extras!!.getString(key2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOverrideActivityResult_shallMerge_added_woIntent_withChallenge() {
|
||||
val key1 = "test1"
|
||||
val key2 = "test2"
|
||||
val extra = Bundle().apply {
|
||||
putString(key1, "test123")
|
||||
putInt(key2, 9999)
|
||||
}
|
||||
|
||||
val key3 = "test3"
|
||||
val intent = Intent().apply {
|
||||
putExtra(key3, 3456L)
|
||||
}
|
||||
|
||||
viewModel.isNewFingerprintAdded = true
|
||||
|
||||
val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
|
||||
assertThat(retResult).isNotNull()
|
||||
|
||||
val retIntent = retResult.data
|
||||
assertThat(retIntent).isNotNull()
|
||||
|
||||
val retExtra = retIntent!!.extras
|
||||
assertThat(retExtra).isNotNull()
|
||||
assertThat(retExtra!!.size).isEqualTo(extra.size + intent.extras!!.size)
|
||||
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
|
||||
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
|
||||
assertThat(retExtra.getLong(key3)).isEqualTo(intent.extras!!.getLong(key3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsMaxEnrolledReached() {
|
||||
val uid = 100
|
||||
fingerprintRepository = newFingerprintRepository(
|
||||
fingerprintManager,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
3
|
||||
)
|
||||
viewModel = FingerprintEnrollmentViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
newAllFalseRequest(application)
|
||||
)
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 0)
|
||||
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 1)
|
||||
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 2)
|
||||
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 3)
|
||||
assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
|
||||
|
||||
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 4)
|
||||
assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetResultFlow_defaultEmpty() = runTest {
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckFinishActivityDuringOnPause_doNothingIfIsSuw() = runTest {
|
||||
viewModel = FingerprintEnrollmentViewModel(
|
||||
application,
|
||||
fingerprintRepository,
|
||||
newIsSuwRequest(application)
|
||||
)
|
||||
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
viewModel.checkFinishActivityDuringOnPause(
|
||||
isActivityFinishing = false,
|
||||
isChangingConfigurations = false,
|
||||
scope = this
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckFinishActivityDuringOnPause_doNothingIfIsWaitingActivity() = runTest {
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
viewModel.isWaitingActivityResult.value = true
|
||||
viewModel.checkFinishActivityDuringOnPause(
|
||||
isActivityFinishing = false,
|
||||
isChangingConfigurations = false,
|
||||
scope = this
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckFinishActivityDuringOnPause_doNothingIfIsActivityFinishing() = runTest {
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
viewModel.checkFinishActivityDuringOnPause(
|
||||
isActivityFinishing = true,
|
||||
isChangingConfigurations = false,
|
||||
scope = this
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckFinishActivityDuringOnPause_doNothingIfIsChangingConfigurations() = runTest {
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
viewModel.checkFinishActivityDuringOnPause(
|
||||
isActivityFinishing = false,
|
||||
isChangingConfigurations = true,
|
||||
scope = this
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckFinishActivityDuringOnPause_defaultFinishSelf() = runTest {
|
||||
val activityResults = listOfSetResultFlow()
|
||||
|
||||
viewModel.checkFinishActivityDuringOnPause(
|
||||
isActivityFinishing = false,
|
||||
isChangingConfigurations = false,
|
||||
scope = backgroundScope
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
assertThat(activityResults.size).isEqualTo(1)
|
||||
assertThat(activityResults[0].resultCode).isEqualTo(BiometricEnrollBase.RESULT_TIMEOUT)
|
||||
assertThat(activityResults[0].data).isEqualTo(null)
|
||||
}
|
||||
|
||||
private fun TestScope.listOfSetResultFlow(): List<ActivityResult> =
|
||||
mutableListOf<ActivityResult>().also {
|
||||
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
|
||||
viewModel.setResultFlow.toList(it)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.text.TextUtils
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics2.ui.model.EnrollmentRequest
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper
|
||||
|
||||
object EnrollmentRequestUtils {
|
||||
@JvmStatic
|
||||
fun newAllFalseRequest(context: Context): EnrollmentRequest {
|
||||
return newRequest(
|
||||
context = context,
|
||||
isSuw = false,
|
||||
isSuwDeferred = false,
|
||||
isSuwPortal = false,
|
||||
isSuwSuggestedActionFlow = false,
|
||||
isSuwFirstRun = false,
|
||||
isFromSettingsSummery = false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newIsSuwRequest(context: Context): EnrollmentRequest {
|
||||
return newRequest(
|
||||
context = context,
|
||||
isSuw = true,
|
||||
isSuwDeferred = false,
|
||||
isSuwPortal = false,
|
||||
isSuwSuggestedActionFlow = false,
|
||||
isSuwFirstRun = false,
|
||||
isFromSettingsSummery = false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newIsSuwDeferredRequest(context: Context): EnrollmentRequest {
|
||||
return newRequest(
|
||||
context = context,
|
||||
isSuw = true,
|
||||
isSuwDeferred = true,
|
||||
isSuwPortal = false,
|
||||
isSuwSuggestedActionFlow = false,
|
||||
isSuwFirstRun = false,
|
||||
isFromSettingsSummery = false, null)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newIsSuwPortalRequest(context: Context): EnrollmentRequest {
|
||||
return newRequest(
|
||||
context = context,
|
||||
isSuw = true,
|
||||
isSuwDeferred = false,
|
||||
isSuwPortal = true,
|
||||
isSuwSuggestedActionFlow = false,
|
||||
isSuwFirstRun = false,
|
||||
isFromSettingsSummery = false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newIsSuwSuggestedActionFlowRequest(
|
||||
context: Context
|
||||
): EnrollmentRequest {
|
||||
return newRequest(
|
||||
context = context,
|
||||
isSuw = true,
|
||||
isSuwDeferred = false,
|
||||
isSuwPortal = false,
|
||||
isSuwSuggestedActionFlow = true,
|
||||
isSuwFirstRun = false,
|
||||
isFromSettingsSummery = false)
|
||||
}
|
||||
|
||||
fun newRequest(
|
||||
context: Context,
|
||||
isSuw: Boolean,
|
||||
isSuwDeferred: Boolean,
|
||||
isSuwPortal: Boolean,
|
||||
isSuwSuggestedActionFlow: Boolean,
|
||||
isSuwFirstRun: Boolean,
|
||||
isFromSettingsSummery: Boolean,
|
||||
theme: String? = null
|
||||
): EnrollmentRequest {
|
||||
val i = Intent()
|
||||
i.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, isSuw)
|
||||
i.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, isSuwDeferred)
|
||||
i.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, isSuwPortal)
|
||||
i.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, isSuwSuggestedActionFlow)
|
||||
i.putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, isSuwFirstRun)
|
||||
i.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, isFromSettingsSummery)
|
||||
if (!TextUtils.isEmpty(theme)) {
|
||||
i.putExtra(WizardManagerHelper.EXTRA_THEME, theme)
|
||||
}
|
||||
return EnrollmentRequest(i, context, true)
|
||||
}
|
||||
}
|
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.utils;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FingerprintRepositoryUtils {
|
||||
|
||||
public static void setupSuwMaxFingerprintsEnrollable(
|
||||
@NonNull Context context,
|
||||
@NonNull Resources mockedResources,
|
||||
int numOfFp) {
|
||||
final int resId = context.getResources().getIdentifier("suw_max_fingerprints_enrollable",
|
||||
"integer", context.getPackageName());
|
||||
when(mockedResources.getInteger(resId)).thenReturn(numOfFp);
|
||||
}
|
||||
|
||||
public static FingerprintRepository newFingerprintRepository(
|
||||
@NonNull FingerprintManager mockedFingerprintManager,
|
||||
@FingerprintSensorProperties.SensorType int sensorType,
|
||||
int maxEnrollmentsPerUser) {
|
||||
|
||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
props.add(new FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
maxEnrollmentsPerUser,
|
||||
new ArrayList<>() /* componentInfo */,
|
||||
sensorType,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */));
|
||||
doAnswer(invocation -> {
|
||||
final IFingerprintAuthenticatorsRegisteredCallback callback =
|
||||
invocation.getArgument(0);
|
||||
callback.onAllAuthenticatorsRegistered(props);
|
||||
return null;
|
||||
}).when(mockedFingerprintManager).addAuthenticatorsRegisteredCallback(any());
|
||||
return new FingerprintRepository(mockedFingerprintManager);
|
||||
}
|
||||
|
||||
public static void setupFingerprintEnrolledFingerprints(
|
||||
@NonNull FingerprintManager mockedFingerprintManager,
|
||||
int userId,
|
||||
int enrolledFingerprints) {
|
||||
final ArrayList<Fingerprint> ret = new ArrayList<>();
|
||||
for (int i = 0; i < enrolledFingerprints; ++i) {
|
||||
ret.add(new Fingerprint("name", 0, 0, 0L));
|
||||
}
|
||||
when(mockedFingerprintManager.getEnrolledFingerprints(userId)).thenReturn(ret);
|
||||
}
|
||||
}
|
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.connecteddevice.display;
|
||||
|
||||
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PREVIOUSLY_SHOWN_LIST_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DISPLAYS_LIST_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SETTINGS_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_TITLE_RESOURCE;
|
||||
import static com.android.settingslib.widget.FooterPreference.KEY_FOOTER;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DisplayPreference;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
|
||||
/** Unit tests for {@link ExternalDisplayPreferenceFragment}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBase {
|
||||
@Nullable
|
||||
private ExternalDisplayPreferenceFragment mFragment;
|
||||
private int mPreferenceIdFromResource;
|
||||
private int mDisplayIdArg = INVALID_DISPLAY;
|
||||
private int mResolutionSelectorDisplayId = INVALID_DISPLAY;
|
||||
@Mock
|
||||
private MetricsLogger mMockedMetricsLogger;
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testCreateAndStart() {
|
||||
initFragment();
|
||||
assertThat(mPreferenceIdFromResource).isEqualTo(EXTERNAL_DISPLAY_SETTINGS_RESOURCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowDisplayList() {
|
||||
var fragment = initFragment();
|
||||
var outState = new Bundle();
|
||||
fragment.onSaveInstanceStateCallback(outState);
|
||||
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isFalse();
|
||||
assertThat(mHandler.getPendingMessages().size()).isEqualTo(1);
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(pref).isNull();
|
||||
verify(mMockedInjector, never()).getAllDisplays();
|
||||
mHandler.flush();
|
||||
assertThat(mHandler.getPendingMessages().size()).isEqualTo(0);
|
||||
verify(mMockedInjector).getAllDisplays();
|
||||
pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
assertThat(pref.getPreferenceCount()).isEqualTo(2);
|
||||
fragment.onSaveInstanceStateCallback(outState);
|
||||
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testLaunchDisplaySettingFromList() {
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
DisplayPreference display1Pref = (DisplayPreference) pref.getPreference(0);
|
||||
DisplayPreference display2Pref = (DisplayPreference) pref.getPreference(1);
|
||||
assertThat(display1Pref.getKey()).isEqualTo("display_id_" + 1);
|
||||
assertThat("" + display1Pref.getTitle()).isEqualTo("HDMI");
|
||||
assertThat("" + display1Pref.getSummary()).isEqualTo("1920 x 1080");
|
||||
display1Pref.onPreferenceClick(display1Pref);
|
||||
assertThat(mDisplayIdArg).isEqualTo(1);
|
||||
verify(mMockedMetricsLogger).writePreferenceClickMetric(display1Pref);
|
||||
assertThat(display2Pref.getKey()).isEqualTo("display_id_" + 2);
|
||||
assertThat("" + display2Pref.getTitle()).isEqualTo("Overlay #1");
|
||||
assertThat("" + display2Pref.getSummary()).isEqualTo("1240 x 780");
|
||||
display2Pref.onPreferenceClick(display2Pref);
|
||||
assertThat(mDisplayIdArg).isEqualTo(2);
|
||||
verify(mMockedMetricsLogger).writePreferenceClickMetric(display2Pref);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowDisplayListForOnlyOneDisplay_PreviouslyShownList() {
|
||||
var fragment = initFragment();
|
||||
// Previously shown list of displays
|
||||
fragment.onActivityCreatedCallback(createBundleForPreviouslyShownList());
|
||||
// Only one display available
|
||||
doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays();
|
||||
mHandler.flush();
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
assertThat(pref.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowEnabledDisplay_OnlyOneDisplayAvailable() {
|
||||
doReturn(true).when(mMockedInjector).isDisplayEnabled(any());
|
||||
// Only one display available
|
||||
doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays();
|
||||
// Init
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory list = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(list).isNull();
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowOneEnabledDisplay_FewAvailable() {
|
||||
mDisplayIdArg = 1;
|
||||
doReturn(true).when(mMockedInjector).isDisplayEnabled(any());
|
||||
initFragment();
|
||||
verify(mMockedInjector, never()).getDisplay(anyInt());
|
||||
mHandler.flush();
|
||||
verify(mMockedInjector).getDisplay(mDisplayIdArg);
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowDisabledDisplay() {
|
||||
mDisplayIdArg = 1;
|
||||
initFragment();
|
||||
verify(mMockedInjector, never()).getDisplay(anyInt());
|
||||
mHandler.flush();
|
||||
verify(mMockedInjector).getDisplay(mDisplayIdArg);
|
||||
var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference(
|
||||
EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
assertThat(mainPref).isNotNull();
|
||||
assertThat("" + mainPref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
assertThat(mainPref.isChecked()).isFalse();
|
||||
assertThat(mainPref.isEnabled()).isTrue();
|
||||
assertThat(mainPref.getOnPreferenceChangeListener()).isNotNull();
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
assertThat(pref).isNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
assertThat(pref).isNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testNoDisplays() {
|
||||
doReturn(new Display[0]).when(mMockedInjector).getAllDisplays();
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference(
|
||||
EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
assertThat(mainPref).isNotNull();
|
||||
assertThat("" + mainPref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
assertThat(mainPref.isChecked()).isFalse();
|
||||
assertThat(mainPref.isEnabled()).isFalse();
|
||||
assertThat(mainPref.getOnPreferenceChangeListener()).isNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testDisplayRotationPreference() {
|
||||
mDisplayIdArg = 1;
|
||||
doReturn(true).when(mMockedInjector).isDisplayEnabled(any());
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getRotationPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE));
|
||||
assertThat(pref.getEntries().length).isEqualTo(4);
|
||||
assertThat(pref.getEntryValues().length).isEqualTo(4);
|
||||
assertThat(pref.getEntryValues()[0].toString()).isEqualTo("0");
|
||||
assertThat(pref.getEntryValues()[1].toString()).isEqualTo("1");
|
||||
assertThat(pref.getEntryValues()[2].toString()).isEqualTo("2");
|
||||
assertThat(pref.getEntryValues()[3].toString()).isEqualTo("3");
|
||||
assertThat(pref.getEntries()[0].length()).isGreaterThan(0);
|
||||
assertThat(pref.getEntries()[1].length()).isGreaterThan(0);
|
||||
assertThat("" + pref.getSummary()).isEqualTo(pref.getEntries()[0].toString());
|
||||
assertThat(pref.getValue()).isEqualTo("0");
|
||||
assertThat(pref.getOnPreferenceChangeListener()).isNotNull();
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
var rotation = 1;
|
||||
doReturn(true).when(mMockedInjector).freezeDisplayRotation(mDisplayIdArg, rotation);
|
||||
assertThat(pref.getOnPreferenceChangeListener().onPreferenceChange(pref, rotation + ""))
|
||||
.isTrue();
|
||||
verify(mMockedInjector).freezeDisplayRotation(mDisplayIdArg, rotation);
|
||||
assertThat(pref.getValue()).isEqualTo(rotation + "");
|
||||
verify(mMockedMetricsLogger).writePreferenceClickMetric(pref);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testDisplayResolutionPreference() {
|
||||
mDisplayIdArg = 1;
|
||||
doReturn(true).when(mMockedInjector).isDisplayEnabled(any());
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getResolutionPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE));
|
||||
assertThat("" + pref.getSummary()).isEqualTo("1920 x 1080");
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
assertThat(pref.getOnPreferenceClickListener()).isNotNull();
|
||||
assertThat(pref.getOnPreferenceClickListener().onPreferenceClick(pref)).isTrue();
|
||||
assertThat(mResolutionSelectorDisplayId).isEqualTo(mDisplayIdArg);
|
||||
verify(mMockedMetricsLogger).writePreferenceClickMetric(pref);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testUseDisplayPreference_EnabledDisplay() {
|
||||
mDisplayIdArg = 1;
|
||||
doReturn(true).when(mMockedInjector).isDisplayEnabled(any());
|
||||
doReturn(true).when(mMockedInjector).enableConnectedDisplay(mDisplayIdArg);
|
||||
doReturn(true).when(mMockedInjector).disableConnectedDisplay(mDisplayIdArg);
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getUseDisplayPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
assertThat(pref.isChecked()).isTrue();
|
||||
assertThat(pref.getOnPreferenceChangeListener()).isNotNull();
|
||||
assertThat(pref.getOnPreferenceChangeListener().onPreferenceChange(pref, false)).isTrue();
|
||||
verify(mMockedInjector).disableConnectedDisplay(mDisplayIdArg);
|
||||
assertThat(pref.isChecked()).isFalse();
|
||||
assertThat(pref.getOnPreferenceChangeListener().onPreferenceChange(pref, true)).isTrue();
|
||||
verify(mMockedInjector).enableConnectedDisplay(mDisplayIdArg);
|
||||
assertThat(pref.isChecked()).isTrue();
|
||||
verify(mMockedMetricsLogger, times(2)).writePreferenceClickMetric(pref);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ExternalDisplayPreferenceFragment initFragment() {
|
||||
if (mFragment != null) {
|
||||
return mFragment;
|
||||
}
|
||||
mFragment = new TestableExternalDisplayPreferenceFragment();
|
||||
mFragment.onCreateCallback(null);
|
||||
mFragment.onActivityCreatedCallback(null);
|
||||
mFragment.onStartCallback();
|
||||
return mFragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Bundle createBundleForPreviouslyShownList() {
|
||||
var state = new Bundle();
|
||||
state.putBoolean(PREVIOUSLY_SHOWN_LIST_KEY, true);
|
||||
return state;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getText(int id) {
|
||||
return mContext.getResources().getText(id).toString();
|
||||
}
|
||||
|
||||
private class TestableExternalDisplayPreferenceFragment extends
|
||||
ExternalDisplayPreferenceFragment {
|
||||
private final View mMockedRootView;
|
||||
private final TextView mEmptyView;
|
||||
private final Activity mMockedActivity;
|
||||
private final FooterPreference mMockedFooterPreference;
|
||||
private final MetricsLogger mLogger;
|
||||
|
||||
TestableExternalDisplayPreferenceFragment() {
|
||||
super(mMockedInjector);
|
||||
mMockedActivity = mock(Activity.class);
|
||||
mMockedRootView = mock(View.class);
|
||||
mMockedFooterPreference = mock(FooterPreference.class);
|
||||
doReturn(KEY_FOOTER).when(mMockedFooterPreference).getKey();
|
||||
mEmptyView = new TextView(mContext);
|
||||
doReturn(mEmptyView).when(mMockedRootView).findViewById(android.R.id.empty);
|
||||
mLogger = mMockedMetricsLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceScreen getPreferenceScreen() {
|
||||
return mPreferenceScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Activity getCurrentActivity() {
|
||||
return mMockedActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return mMockedRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmptyView(View view) {
|
||||
assertThat(view).isEqualTo(mEmptyView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getEmptyView() {
|
||||
return mEmptyView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPreferencesFromResource(int resource) {
|
||||
mPreferenceIdFromResource = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
FooterPreference getFooterPreference(@NonNull Context context) {
|
||||
return mMockedFooterPreference;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDisplayIdArg() {
|
||||
return mDisplayIdArg;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void launchResolutionSelector(@NonNull Context context, int displayId) {
|
||||
mResolutionSelectorDisplayId = displayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void launchDisplaySettings(final int displayId) {
|
||||
mDisplayIdArg = displayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writePreferenceClickMetric(Preference preference) {
|
||||
mLogger.writePreferenceClickMetric(preference);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface allowing to mock and spy on log events.
|
||||
*/
|
||||
public interface MetricsLogger {
|
||||
|
||||
/**
|
||||
* On preference click metric
|
||||
*/
|
||||
void writePreferenceClickMetric(Preference preference);
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.connecteddevice.display;
|
||||
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.VIRTUAL_DISPLAY_PACKAGE_NAME_SYSTEM_PROPERTY;
|
||||
import static com.android.settings.flags.Flags.FLAG_ROTATION_CONNECTED_DISPLAY_SETTING;
|
||||
import static com.android.settings.flags.Flags.FLAG_RESOLUTION_AND_ENABLE_CONNECTED_DISPLAY_SETTING;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.hardware.display.IDisplayManager;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayAdjustments;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.server.testutils.TestHandler;
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.DisplayListener;
|
||||
import com.android.settings.flags.FakeFeatureFlagsImpl;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
public class ExternalDisplayTestBase {
|
||||
@Mock
|
||||
ExternalDisplaySettingsConfiguration.Injector mMockedInjector;
|
||||
@Mock
|
||||
IDisplayManager mMockedIDisplayManager;
|
||||
Resources mResources;
|
||||
DisplayManagerGlobal mDisplayManagerGlobal;
|
||||
FakeFeatureFlagsImpl mFlags = new FakeFeatureFlagsImpl();
|
||||
Context mContext;
|
||||
DisplayListener mListener;
|
||||
TestHandler mHandler = new TestHandler(null);
|
||||
PreferenceManager mPreferenceManager;
|
||||
PreferenceScreen mPreferenceScreen;
|
||||
Display[] mDisplays;
|
||||
|
||||
/**
|
||||
* Setup.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(mContext.getResources());
|
||||
doReturn(mResources).when(mContext).getResources();
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
doReturn(0).when(mMockedIDisplayManager).getPreferredWideGamutColorSpaceId();
|
||||
mDisplayManagerGlobal = new DisplayManagerGlobal(mMockedIDisplayManager);
|
||||
mFlags.setFlag(FLAG_ROTATION_CONNECTED_DISPLAY_SETTING, true);
|
||||
mFlags.setFlag(FLAG_RESOLUTION_AND_ENABLE_CONNECTED_DISPLAY_SETTING, true);
|
||||
mDisplays = new Display[] {
|
||||
createDefaultDisplay(), createExternalDisplay(), createOverlayDisplay()};
|
||||
doReturn(mDisplays).when(mMockedInjector).getAllDisplays();
|
||||
doReturn(mDisplays).when(mMockedInjector).getEnabledDisplays();
|
||||
for (var display : mDisplays) {
|
||||
doReturn(display).when(mMockedInjector).getDisplay(display.getDisplayId());
|
||||
}
|
||||
doReturn(mFlags).when(mMockedInjector).getFlags();
|
||||
doReturn(mHandler).when(mMockedInjector).getHandler();
|
||||
doReturn("").when(mMockedInjector).getSystemProperty(
|
||||
VIRTUAL_DISPLAY_PACKAGE_NAME_SYSTEM_PROPERTY);
|
||||
doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
|
||||
doAnswer((arg) -> {
|
||||
mListener = arg.getArgument(0);
|
||||
return null;
|
||||
}).when(mMockedInjector).registerDisplayListener(any());
|
||||
doReturn(0).when(mMockedInjector).getDisplayUserRotation(anyInt());
|
||||
doReturn(mContext).when(mMockedInjector).getContext();
|
||||
}
|
||||
|
||||
Display createDefaultDisplay() throws RemoteException {
|
||||
int displayId = 0;
|
||||
var displayInfo = new DisplayInfo();
|
||||
doReturn(displayInfo).when(mMockedIDisplayManager).getDisplayInfo(displayId);
|
||||
displayInfo.displayId = displayId;
|
||||
displayInfo.name = "Built-in";
|
||||
displayInfo.type = Display.TYPE_INTERNAL;
|
||||
displayInfo.supportedModes = new Display.Mode[]{
|
||||
new Display.Mode(0, 2048, 1024, 60, 60, new float[0],
|
||||
new int[0])};
|
||||
displayInfo.appsSupportedModes = displayInfo.supportedModes;
|
||||
return createDisplay(displayInfo);
|
||||
}
|
||||
|
||||
Display createExternalDisplay() throws RemoteException {
|
||||
int displayId = 1;
|
||||
var displayInfo = new DisplayInfo();
|
||||
doReturn(displayInfo).when(mMockedIDisplayManager).getDisplayInfo(displayId);
|
||||
displayInfo.displayId = displayId;
|
||||
displayInfo.name = "HDMI";
|
||||
displayInfo.type = Display.TYPE_EXTERNAL;
|
||||
displayInfo.supportedModes = new Display.Mode[]{
|
||||
new Display.Mode(0, 1920, 1080, 60, 60, new float[0], new int[0]),
|
||||
new Display.Mode(1, 800, 600, 60, 60, new float[0], new int[0]),
|
||||
new Display.Mode(2, 320, 240, 70, 70, new float[0], new int[0]),
|
||||
new Display.Mode(3, 640, 480, 60, 60, new float[0], new int[0]),
|
||||
new Display.Mode(4, 640, 480, 50, 60, new float[0], new int[0]),
|
||||
new Display.Mode(5, 2048, 1024, 60, 60, new float[0], new int[0]),
|
||||
new Display.Mode(6, 720, 480, 60, 60, new float[0], new int[0])};
|
||||
displayInfo.appsSupportedModes = displayInfo.supportedModes;
|
||||
return createDisplay(displayInfo);
|
||||
}
|
||||
|
||||
Display createOverlayDisplay() throws RemoteException {
|
||||
int displayId = 2;
|
||||
var displayInfo = new DisplayInfo();
|
||||
doReturn(displayInfo).when(mMockedIDisplayManager).getDisplayInfo(displayId);
|
||||
displayInfo.displayId = displayId;
|
||||
displayInfo.name = "Overlay #1";
|
||||
displayInfo.type = Display.TYPE_OVERLAY;
|
||||
displayInfo.supportedModes = new Display.Mode[]{
|
||||
new Display.Mode(0, 1240, 780, 60, 60, new float[0],
|
||||
new int[0])};
|
||||
displayInfo.appsSupportedModes = displayInfo.supportedModes;
|
||||
return createDisplay(displayInfo);
|
||||
}
|
||||
|
||||
Display createDisplay(DisplayInfo displayInfo) {
|
||||
return new Display(mDisplayManagerGlobal, displayInfo.displayId, displayInfo,
|
||||
(DisplayAdjustments) null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.connecteddevice.display;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Display;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
|
||||
/** Unit tests for {@link ExternalDisplayUpdater}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExternalDisplayUpdaterTest extends ExternalDisplayTestBase {
|
||||
|
||||
private ExternalDisplayUpdater mUpdater;
|
||||
@Mock
|
||||
private DevicePreferenceCallback mMockedCallback;
|
||||
@Mock
|
||||
private Drawable mMockedDrawable;
|
||||
private RestrictedPreference mPreferenceAdded;
|
||||
private RestrictedPreference mPreferenceRemoved;
|
||||
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
super.setUp();
|
||||
mUpdater = new TestableExternalDisplayUpdater(mMockedCallback, /*metricsCategory=*/ 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreferenceAdded() {
|
||||
doAnswer((v) -> {
|
||||
mPreferenceAdded = v.getArgument(0);
|
||||
return null;
|
||||
}).when(mMockedCallback).onDeviceAdded(any());
|
||||
mUpdater.initPreference(mContext, mMockedInjector);
|
||||
mUpdater.registerCallback();
|
||||
mHandler.flush();
|
||||
assertThat(mPreferenceAdded).isNotNull();
|
||||
var summary = mPreferenceAdded.getSummary();
|
||||
assertThat(summary).isNotNull();
|
||||
assertThat(summary.length()).isGreaterThan(0);
|
||||
var title = mPreferenceAdded.getTitle();
|
||||
assertThat(title).isNotNull();
|
||||
assertThat(title.length()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreferenceRemoved() {
|
||||
doAnswer((v) -> {
|
||||
mPreferenceAdded = v.getArgument(0);
|
||||
return null;
|
||||
}).when(mMockedCallback).onDeviceAdded(any());
|
||||
doAnswer((v) -> {
|
||||
mPreferenceRemoved = v.getArgument(0);
|
||||
return null;
|
||||
}).when(mMockedCallback).onDeviceRemoved(any());
|
||||
mUpdater.initPreference(mContext, mMockedInjector);
|
||||
mUpdater.registerCallback();
|
||||
mHandler.flush();
|
||||
assertThat(mPreferenceAdded).isNotNull();
|
||||
assertThat(mPreferenceRemoved).isNull();
|
||||
// Remove display
|
||||
doReturn(new Display[0]).when(mMockedInjector).getAllDisplays();
|
||||
doReturn(new Display[0]).when(mMockedInjector).getEnabledDisplays();
|
||||
mListener.onDisplayRemoved(1);
|
||||
mHandler.flush();
|
||||
assertThat(mPreferenceRemoved).isEqualTo(mPreferenceAdded);
|
||||
}
|
||||
|
||||
class TestableExternalDisplayUpdater extends ExternalDisplayUpdater {
|
||||
TestableExternalDisplayUpdater(
|
||||
DevicePreferenceCallback callback,
|
||||
int metricsCategory) {
|
||||
super(callback, metricsCategory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected RestrictedLockUtils.EnforcedAdmin checkIfUsbDataSignalingIsDisabled(
|
||||
Context context) {
|
||||
// if null is returned - usb signalling is enabled
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Drawable getDrawable(Context context) {
|
||||
return mMockedDrawable;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.connecteddevice.display;
|
||||
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.DISPLAY_MODE_LIMIT_OVERRIDE_PROP;
|
||||
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.MORE_OPTIONS_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.TOP_OPTIONS_KEY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
|
||||
/** Unit tests for {@link ResolutionPreferenceFragment}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase {
|
||||
@Nullable
|
||||
private ResolutionPreferenceFragment mFragment;
|
||||
private int mPreferenceIdFromResource;
|
||||
private int mDisplayIdArg = INVALID_DISPLAY;
|
||||
@Mock
|
||||
private MetricsLogger mMockedMetricsLogger;
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testCreateAndStart() {
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
assertThat(mPreferenceIdFromResource).isEqualTo(
|
||||
EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE);
|
||||
var pref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
|
||||
assertThat(pref).isNull();
|
||||
pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
|
||||
assertThat(pref).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testCreateAndStartDefaultDisplayNotAllowed() {
|
||||
mDisplayIdArg = 0;
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
var pref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
|
||||
assertThat(pref).isNull();
|
||||
pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
|
||||
assertThat(pref).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testModePreferences_modeLimitFlagIsOn_noOverride() {
|
||||
doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
|
||||
doReturn(null).when(mMockedInjector).getSystemProperty(
|
||||
DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
|
||||
var topAndMorePref = runTestModePreferences();
|
||||
PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
|
||||
assertThat(topPref.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(morePref.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testModePreferences_noModeLimitFlag_overrideIsTrue() {
|
||||
doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
|
||||
doReturn("true").when(mMockedInjector).getSystemProperty(
|
||||
DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
|
||||
var topAndMorePref = runTestModePreferences();
|
||||
PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
|
||||
assertThat(topPref.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(morePref.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testModePreferences_noModeLimitFlag_noOverride() {
|
||||
doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
|
||||
doReturn(null).when(mMockedInjector).getSystemProperty(
|
||||
DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
|
||||
var topAndMorePref = runTestModePreferences();
|
||||
PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
|
||||
assertThat(topPref.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(morePref.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testModePreferences_modeLimitFlagIsOn_butOverrideIsFalse() {
|
||||
doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
|
||||
doReturn("false").when(mMockedInjector).getSystemProperty(
|
||||
DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
|
||||
var topAndMorePref = runTestModePreferences();
|
||||
PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
|
||||
assertThat(topPref.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(morePref.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testModeChange() {
|
||||
mDisplayIdArg = 1;
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
|
||||
assertThat(topPref).isNotNull();
|
||||
var modePref = (SelectorWithWidgetPreference) topPref.getPreference(1);
|
||||
modePref.onClick();
|
||||
var mode = mDisplays[mDisplayIdArg].getSupportedModes()[1];
|
||||
verify(mMockedInjector).setUserPreferredDisplayMode(mDisplayIdArg, mode);
|
||||
}
|
||||
|
||||
private Pair<PreferenceCategory, PreferenceCategory> runTestModePreferences() {
|
||||
mDisplayIdArg = 1;
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
|
||||
assertThat(topPref).isNotNull();
|
||||
PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
|
||||
assertThat(morePref).isNotNull();
|
||||
return new Pair<>(topPref, morePref);
|
||||
}
|
||||
|
||||
private void initFragment() {
|
||||
if (mFragment != null) {
|
||||
return;
|
||||
}
|
||||
mFragment = new TestableResolutionPreferenceFragment();
|
||||
mFragment.onCreateCallback(null);
|
||||
mFragment.onActivityCreatedCallback(null);
|
||||
mFragment.onStartCallback();
|
||||
}
|
||||
|
||||
private class TestableResolutionPreferenceFragment extends ResolutionPreferenceFragment {
|
||||
private final View mMockedRootView;
|
||||
private final TextView mEmptyView;
|
||||
private final Resources mMockedResources;
|
||||
private final MetricsLogger mLogger;
|
||||
TestableResolutionPreferenceFragment() {
|
||||
super(mMockedInjector);
|
||||
mMockedResources = mock(Resources.class);
|
||||
doReturn(61).when(mMockedResources).getInteger(
|
||||
com.android.internal.R.integer.config_externalDisplayPeakRefreshRate);
|
||||
doReturn(1920).when(mMockedResources).getInteger(
|
||||
com.android.internal.R.integer.config_externalDisplayPeakWidth);
|
||||
doReturn(1080).when(mMockedResources).getInteger(
|
||||
com.android.internal.R.integer.config_externalDisplayPeakHeight);
|
||||
doReturn(true).when(mMockedResources).getBoolean(
|
||||
com.android.internal.R.bool.config_refreshRateSynchronizationEnabled);
|
||||
mMockedRootView = mock(View.class);
|
||||
mEmptyView = new TextView(mContext);
|
||||
doReturn(mEmptyView).when(mMockedRootView).findViewById(android.R.id.empty);
|
||||
mLogger = mMockedMetricsLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceScreen getPreferenceScreen() {
|
||||
return mPreferenceScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return mMockedRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmptyView(View view) {
|
||||
assertThat(view).isEqualTo(mEmptyView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getEmptyView() {
|
||||
return mEmptyView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPreferencesFromResource(int resource) {
|
||||
mPreferenceIdFromResource = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDisplayIdArg() {
|
||||
return mDisplayIdArg;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writePreferenceClickMetric(Preference preference) {
|
||||
mLogger.writePreferenceClickMetric(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected Resources getResources(@NonNull Context context) {
|
||||
return mMockedResources;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface allowing to mock and spy on log events.
|
||||
*/
|
||||
public interface MetricsLogger {
|
||||
/**
|
||||
* On preference click metric
|
||||
*/
|
||||
void writePreferenceClickMetric(Preference preference);
|
||||
}
|
||||
}
|
@@ -16,13 +16,9 @@
|
||||
|
||||
package com.android.settings.development.bluetooth;
|
||||
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BTSTACK_LOG_MODE_VERBOSE_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BTSTACK_LOG_MODE_DEBUG_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BTSTACK_LOG_MODE_INFO_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BTSTACK_LOG_MODE_WARN_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BTSTACK_LOG_MODE_ERROR_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BT_LOG_LEVEL_DEFAULT_INDEX;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BT_LOG_LEVEL_PROP;
|
||||
import static com.android.settings.development.bluetooth.BluetoothStackLogPreferenceController.BT_LOG_LEVEL_PROP_PERSIST;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -37,18 +33,21 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@Ignore("b/339148064")
|
||||
public class BluetoothStackLogPreferenceControllerTest {
|
||||
private static final String TAG = "BluetoothStackLogPreferenceControllerTest";
|
||||
private static final String COM_ANDROID_SETTINGS = "com.android.settings";
|
||||
private static final String TYPE_ARRAY = "array";
|
||||
|
||||
@Mock private Context mContext;
|
||||
private static final String XML_DEFINED_PREFERENCE_KEY = "bt_stack_log_level";
|
||||
private static final String XML_DEFINED_ENTRIES_RESOURCE = "bt_stack_log_level_entries";
|
||||
private static final String XML_DEFINED_VALUES_RESOURCE = "bt_stack_log_level_values";
|
||||
|
||||
private static final String PROPERTY_CLEARED = "";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private ListPreference mPreference;
|
||||
private PreferenceManager mPreferenceManager;
|
||||
@@ -61,7 +60,6 @@ public class BluetoothStackLogPreferenceControllerTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
if (Looper.myLooper() == null) {
|
||||
@@ -71,12 +69,11 @@ public class BluetoothStackLogPreferenceControllerTest {
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
mPreference = new ListPreference(mContext);
|
||||
|
||||
mController = new BluetoothStackLogPreferenceController(mContext);
|
||||
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
mPreference.setEntries(com.android.settings.R.array.bt_stack_log_level_entries);
|
||||
mPreference.setEntryValues(com.android.settings.R.array.bt_stack_log_level_values);
|
||||
mPreference.setEntries(getStringArrayResourceId(XML_DEFINED_ENTRIES_RESOURCE));
|
||||
mPreference.setEntryValues(getStringArrayResourceId(XML_DEFINED_VALUES_RESOURCE));
|
||||
|
||||
mPreferenceScreen.addPreference(mPreference);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
@@ -86,134 +83,109 @@ public class BluetoothStackLogPreferenceControllerTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that default log level is set to INFO
|
||||
* Get the resource ID associated with a resource name
|
||||
*
|
||||
* This looks up the resource id by name using our device's context. This way, we can avoid
|
||||
* hardcoding a resource ID or value from the R class which may not match the resource IDs on
|
||||
* the device under test.
|
||||
*
|
||||
* Usage: int valuesResId = getStringArrayResource("bt_stack_log_level_values");
|
||||
* Usage: int entriesResId = getStringArrayResource("bt_stack_log_level_entries");
|
||||
*
|
||||
* @param res - The resource name to look up
|
||||
* @return The integer resource ID corresponding to the given resource name
|
||||
*/
|
||||
@Test
|
||||
public void verifyDefaultState_enablesDefaultLogLevelEntriesAndValuesSameSize() {
|
||||
mController.onPreferenceChange(mPreference, mController.getDefaultModeIndex());
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
[BTSTACK_LOG_MODE_INFO_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_INFO_INDEX].toString());
|
||||
public int getStringArrayResourceId(String res) {
|
||||
return mContext.getResources().getIdentifier(res, TYPE_ARRAY, COM_ANDROID_SETTINGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that log level is changed to VERBOSE when VERBOSE is selected
|
||||
* Test that, for each possible value a user can select, our controller properly handles the
|
||||
* value to update the underlying system property _and_ set the UI entry to the proper value.
|
||||
*/
|
||||
@Test
|
||||
public void onPreferenceChanged_enableBluetoothStackVerboseLogLevel() {
|
||||
mController.onPreferenceChange(mPreference, mListValues[BTSTACK_LOG_MODE_VERBOSE_INDEX]
|
||||
.toString());
|
||||
public void onPreferenceChange_withEachValue_uiSetProperlyAndAllValuesWrittenToProperties() {
|
||||
for (int index = 0; index < mListValues.length; index++) {
|
||||
String value = mListValues[index].toString();
|
||||
String entry = mListEntries[index].toString();
|
||||
|
||||
final String persistedLogLevel = SystemProperties.get(
|
||||
BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY);
|
||||
assertThat(persistedLogLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_VERBOSE_INDEX]
|
||||
.toString());
|
||||
assertThat(logLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_VERBOSE_INDEX].toString());
|
||||
mController.onPreferenceChange(mPreference, value);
|
||||
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
[BTSTACK_LOG_MODE_VERBOSE_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_VERBOSE_INDEX].toString());
|
||||
final String persistedLogLevel = SystemProperties.get(BT_LOG_LEVEL_PROP_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BT_LOG_LEVEL_PROP);
|
||||
final String currentValue = mPreference.getValue().toString();
|
||||
final String currentEntry = mPreference.getEntry().toString();
|
||||
final String currentSummary = mPreference.getSummary().toString();
|
||||
final int currentIndex = mPreference.findIndexOfValue(currentValue);
|
||||
|
||||
assertThat(persistedLogLevel).isEqualTo(value);
|
||||
assertThat(logLevel).isEqualTo(value);
|
||||
assertThat(currentIndex).isEqualTo(index);
|
||||
assertThat(currentValue).isEqualTo(value);
|
||||
assertThat(currentEntry).isEqualTo(entry);
|
||||
assertThat(currentSummary).isEqualTo(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that log level is changed to DEBUG when DEBUG is selected
|
||||
* Test that, for each possible log tag log level value, our controller properly handles the
|
||||
* value to set the UI entry to the proper value.
|
||||
*/
|
||||
@Test
|
||||
public void onPreferenceChanged_enableBluetoothStackDebugLogLevel() {
|
||||
mController.onPreferenceChange(mPreference, mListValues[BTSTACK_LOG_MODE_DEBUG_INDEX]
|
||||
.toString());
|
||||
public void updateState_withEachValue_uiSetProperly() {
|
||||
for (int index = 0; index < mListValues.length; index++) {
|
||||
String value = mListValues[index].toString();
|
||||
String entry = mListEntries[index].toString();
|
||||
|
||||
final String persistedLogLevel = SystemProperties.get(
|
||||
BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY);
|
||||
assertThat(persistedLogLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_DEBUG_INDEX]
|
||||
.toString());
|
||||
assertThat(logLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_DEBUG_INDEX].toString());
|
||||
SystemProperties.set(BT_LOG_LEVEL_PROP_PERSIST, value);
|
||||
SystemProperties.set(BT_LOG_LEVEL_PROP, value);
|
||||
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
[BTSTACK_LOG_MODE_DEBUG_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_DEBUG_INDEX].toString());
|
||||
mController.updateState(mPreference);
|
||||
|
||||
final String currentValue = mPreference.getValue().toString();
|
||||
final String currentEntry = mPreference.getEntry().toString();
|
||||
final String currentSummary = mPreference.getSummary().toString();
|
||||
final int currentIndex = mPreference.findIndexOfValue(currentValue);
|
||||
|
||||
assertThat(currentIndex).isEqualTo(index);
|
||||
assertThat(currentValue).isEqualTo(value);
|
||||
assertThat(currentEntry).isEqualTo(entry);
|
||||
assertThat(currentSummary).isEqualTo(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that log level is changed to INFO when INFO is selected
|
||||
* Test that our controller reverts the log level back to a missing/default value when we're
|
||||
* notified that Developer Options has been disabled.
|
||||
*/
|
||||
@Test
|
||||
public void onPreferenceChanged_enableBluetoothStackInfoLogLevel() {
|
||||
mController.onPreferenceChange(mPreference, mListValues[BTSTACK_LOG_MODE_INFO_INDEX]
|
||||
.toString());
|
||||
public void onDeveloperOptionsSwitchDisabled_preferenceSetToDefault() {
|
||||
mController.onDeveloperOptionsSwitchDisabled();
|
||||
|
||||
final String persistedLogLevel = SystemProperties.get(
|
||||
BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY);
|
||||
assertThat(persistedLogLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_INFO_INDEX]
|
||||
.toString());
|
||||
assertThat(logLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_INFO_INDEX].toString());
|
||||
final String defaultEntry = mListEntries[BT_LOG_LEVEL_DEFAULT_INDEX].toString();
|
||||
final String defaultValue = mListValues[BT_LOG_LEVEL_DEFAULT_INDEX].toString();
|
||||
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
[BTSTACK_LOG_MODE_INFO_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_INFO_INDEX].toString());
|
||||
final String persistedLogLevel = SystemProperties.get(BT_LOG_LEVEL_PROP_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BT_LOG_LEVEL_PROP);
|
||||
final String currentValue = mPreference.getValue().toString();
|
||||
final String currentEntry = mPreference.getEntry().toString();
|
||||
final String currentSummary = mPreference.getSummary().toString();
|
||||
final int currentIndex = mPreference.findIndexOfValue(currentValue);
|
||||
|
||||
assertThat(persistedLogLevel).isEqualTo(PROPERTY_CLEARED);
|
||||
assertThat(logLevel).isEqualTo(PROPERTY_CLEARED);
|
||||
assertThat(currentIndex).isEqualTo(BT_LOG_LEVEL_DEFAULT_INDEX);
|
||||
assertThat(currentValue).isEqualTo(defaultValue);
|
||||
assertThat(currentEntry).isEqualTo(defaultEntry);
|
||||
assertThat(currentSummary).isEqualTo(defaultEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that log level is changed to WARN when WARN is selected
|
||||
* Test that our preference key returned by our controller matches the one defined in the XML
|
||||
* definition.
|
||||
*/
|
||||
@Test
|
||||
public void onPreferenceChanged_enableBluetoothStackWarnLogLevel() {
|
||||
mController.onPreferenceChange(mPreference, mListValues[BTSTACK_LOG_MODE_WARN_INDEX]
|
||||
.toString());
|
||||
|
||||
final String persistedLogLevel = SystemProperties.get(
|
||||
BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY);
|
||||
assertThat(persistedLogLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_WARN_INDEX]
|
||||
.toString());
|
||||
assertThat(logLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_WARN_INDEX].toString());
|
||||
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
|
||||
[BTSTACK_LOG_MODE_WARN_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_WARN_INDEX].toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that log level is changed to ERROR when ERROR is selected
|
||||
*/
|
||||
@Test
|
||||
public void onPreferenceChanged_enableBluetoothStackErrorLogLevel() {
|
||||
mController.onPreferenceChange(mPreference, mListValues[BTSTACK_LOG_MODE_ERROR_INDEX]
|
||||
.toString());
|
||||
|
||||
final String persistedLogLevel = SystemProperties.get(
|
||||
BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST);
|
||||
final String logLevel = SystemProperties.get(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY);
|
||||
assertThat(persistedLogLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_ERROR_INDEX]
|
||||
.toString());
|
||||
assertThat(logLevel).isEqualTo(mListValues[BTSTACK_LOG_MODE_ERROR_INDEX].toString());
|
||||
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues
|
||||
[BTSTACK_LOG_MODE_ERROR_INDEX].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries
|
||||
[BTSTACK_LOG_MODE_ERROR_INDEX].toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that preference is disabled when developer options is disabled
|
||||
* Log level is also reset to default
|
||||
*/
|
||||
@Test
|
||||
public void onDeveloperOptionsDisabled_shouldDisablePreference() {
|
||||
mController.onDeveloperOptionsDisabled();
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.getValue().toString()).isEqualTo(mListValues[mController
|
||||
.getDefaultModeIndex()].toString());
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(mListEntries[mController
|
||||
.getDefaultModeIndex()].toString());
|
||||
public void getPreferenceKey_matchesXmlDefinedPreferenceKey() {
|
||||
assertThat(mController.getPreferenceKey()).isEqualTo(XML_DEFINED_PREFERENCE_KEY);
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@ import android.util.Log;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.media_drm.Flags;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.preference.SwitchPreference;
|
||||
@@ -65,10 +67,10 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_FORCE_L3_ENABLED)
|
||||
public void updateState_flagEnabled_checkPreference() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED);
|
||||
mController.updateState(mPreference);
|
||||
assumeTrue(mPreference.isEnabled());
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse();
|
||||
|
||||
@@ -85,33 +87,22 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest {
|
||||
assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse();
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
// Test flag rollback
|
||||
mController.setChecked(true);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isTrue();
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_FORCE_L3_ENABLED);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(Flags.FLAG_FORCE_L3_ENABLED)
|
||||
public void updateState_flagDisabled_checkPreference() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_FORCE_L3_ENABLED);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_FORCE_L3_ENABLED)
|
||||
public void updateState_checkWidevine() throws Exception {
|
||||
try (MediaDrm drm = new MediaDrm(WIDEVINE_UUID)) {
|
||||
assumeTrue(drm.getPropertyString("securityLevel").equals("L1"));
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED);
|
||||
mController.updateState(mPreference);
|
||||
assumeTrue(mPreference.isEnabled());
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
} catch (UnsupportedSchemeException ex) {
|
||||
assumeNoException(ex);
|
||||
}
|
||||
@@ -139,11 +130,11 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_FORCE_L3_ENABLED)
|
||||
public void updateState_checkWhenWidevineReady() throws Exception {
|
||||
try (MediaDrm drm = new MediaDrm(WIDEVINE_UUID)) {
|
||||
if (drm.getPropertyString("securityLevel").equals("L1")) {
|
||||
String version = drm.getPropertyString(MediaDrm.PROPERTY_VERSION);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED);
|
||||
mController.updateState(mPreference);
|
||||
if (Integer.parseInt(version.split("\\.", 2)[0]) >= 19) {
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
|
@@ -22,14 +22,21 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.Flags;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
@@ -45,6 +52,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
@@ -53,6 +61,9 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BuildNumberPreferenceControllerTest {
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule =
|
||||
DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String KEY_BUILD_NUMBER = "build_number";
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
@@ -60,6 +71,7 @@ public class BuildNumberPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private UserManager mUserManager;
|
||||
private BiometricManager mBiometricManager;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Lifecycle mLifecycle;
|
||||
private FakeFeatureFactory mFactory;
|
||||
@@ -76,7 +88,13 @@ public class BuildNumberPreferenceControllerTest {
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mUserManager = (UserManager) spy(mContext.getSystemService(Context.USER_SERVICE));
|
||||
mBiometricManager = spy(mContext.getSystemService(BiometricManager.class));
|
||||
|
||||
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
|
||||
when(mContext.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
|
||||
when(mBiometricManager.canAuthenticate(mContext.getUserId(),
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
|
||||
mFactory = FakeFeatureFactory.setupForTest();
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
@@ -156,7 +174,7 @@ public class BuildNumberPreferenceControllerTest {
|
||||
@Test
|
||||
public void onActivityResult_notConfirmPasswordRequest_doNothing() {
|
||||
final boolean activityResultHandled = mController.onActivityResult(
|
||||
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF + 1,
|
||||
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF + 2,
|
||||
Activity.RESULT_OK,
|
||||
null);
|
||||
|
||||
@@ -177,6 +195,7 @@ public class BuildNumberPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
|
||||
@@ -188,4 +207,56 @@ public class BuildNumberPreferenceControllerTest {
|
||||
assertThat(activityResultHandled).isTrue();
|
||||
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void onActivityResult_confirmPasswordRequestCompleted_launchBiometricPrompt() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
when(mBiometricManager.canAuthenticate(mContext.getUserId(),
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
|
||||
|
||||
final boolean activityResultHandled = mController.onActivityResult(
|
||||
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
|
||||
Activity.RESULT_OK,
|
||||
null);
|
||||
|
||||
assertThat(activityResultHandled).isTrue();
|
||||
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
|
||||
verify(mFragment).startActivityForResult(any(),
|
||||
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void onActivityResult_confirmPasswordRequestCompleted_mandatoryBiometricsError() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
when(mBiometricManager.canAuthenticate(mContext.getUserId(),
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
|
||||
|
||||
final boolean activityResultHandled = mController.onActivityResult(
|
||||
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
|
||||
Activity.RESULT_OK,
|
||||
null);
|
||||
|
||||
assertThat(activityResultHandled).isTrue();
|
||||
verify(mFragment, never()).startActivityForResult(any(),
|
||||
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_confirmBiometricAuthentication_enableDevPref() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
|
||||
Looper.prepare();
|
||||
final boolean activityResultHandled = mController.onActivityResult(
|
||||
BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF,
|
||||
Activity.RESULT_OK,
|
||||
null);
|
||||
|
||||
assertThat(activityResultHandled).isTrue();
|
||||
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isTrue();
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.fingerprint2.domain.interactor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.hardware.biometrics.ComponentInfoInternal
|
||||
import android.hardware.biometrics.SensorLocationInternal
|
||||
@@ -30,23 +29,37 @@ import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
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.data.repository.FingerprintEnrollmentRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSettingsRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.UserRepo
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AuthenticateInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.CanEnrollFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollFingerprintInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrolledFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.GenerateChallengeInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.RemoveFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.RenameFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnrollFingerprintsInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrollFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.GenerateChallengeInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RemoveFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RenameFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.last
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -75,13 +88,28 @@ import org.mockito.stubbing.OngoingStubbing
|
||||
class FingerprintManagerInteractorTest {
|
||||
|
||||
@JvmField @Rule var rule = MockitoJUnit.rule()
|
||||
private lateinit var underTest: FingerprintManagerInteractor
|
||||
private var context: Context = ApplicationProvider.getApplicationContext()
|
||||
private lateinit var enrolledFingerprintsInteractorUnderTest: EnrolledFingerprintsInteractor
|
||||
private lateinit var generateChallengeInteractorUnderTest: GenerateChallengeInteractor
|
||||
private lateinit var removeFingerprintsInteractorUnderTest: RemoveFingerprintInteractor
|
||||
private lateinit var renameFingerprintsInteractorUnderTest: RenameFingerprintInteractor
|
||||
private lateinit var authenticateInteractorImplUnderTest: AuthenticateInteractorImpl
|
||||
private lateinit var canEnrollFingerprintsInteractorUnderTest: CanEnrollFingerprintsInteractor
|
||||
private lateinit var enrollInteractorUnderTest: EnrollFingerprintInteractor
|
||||
|
||||
private val userId = 0
|
||||
private var backgroundDispatcher = StandardTestDispatcher()
|
||||
@Mock private lateinit var fingerprintManager: FingerprintManager
|
||||
@Mock private lateinit var gateKeeperPasswordProvider: GatekeeperPasswordProvider
|
||||
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
private var backgroundScope = testScope.backgroundScope
|
||||
private val flow: FingerprintFlow = Default
|
||||
private val maxFingerprints = 5
|
||||
private val currUser = MutableStateFlow(0)
|
||||
private val userRepo =
|
||||
object : UserRepo {
|
||||
override val currentUser: Flow<Int> = currUser
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@@ -89,7 +117,7 @@ class FingerprintManagerInteractorTest {
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
maxFingerprints,
|
||||
listOf<ComponentInfoInternal>(),
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
false /* halControlsIllumination */,
|
||||
@@ -97,20 +125,37 @@ class FingerprintManagerInteractorTest {
|
||||
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
|
||||
)
|
||||
.toFingerprintSensor()
|
||||
|
||||
val fingerprintSensorRepository =
|
||||
object : FingerprintSensorRepository {
|
||||
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensor)
|
||||
override val hasSideFps: Flow<Boolean> = flowOf(false)
|
||||
}
|
||||
|
||||
underTest =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context,
|
||||
backgroundDispatcher,
|
||||
val settingsRepository = FingerprintSettingsRepositoryImpl(maxFingerprints)
|
||||
val fingerprintEnrollmentRepository =
|
||||
FingerprintEnrollmentRepositoryImpl(
|
||||
fingerprintManager,
|
||||
fingerprintSensorRepository,
|
||||
gateKeeperPasswordProvider,
|
||||
FingerprintEnrollInteractorImpl(context, fingerprintManager, Default),
|
||||
userRepo,
|
||||
settingsRepository,
|
||||
backgroundDispatcher,
|
||||
backgroundScope,
|
||||
)
|
||||
|
||||
enrolledFingerprintsInteractorUnderTest =
|
||||
EnrolledFingerprintsInteractorImpl(fingerprintManager, userId)
|
||||
generateChallengeInteractorUnderTest =
|
||||
GenerateChallengeInteractorImpl(fingerprintManager, userId, gateKeeperPasswordProvider)
|
||||
removeFingerprintsInteractorUnderTest =
|
||||
RemoveFingerprintsInteractorImpl(fingerprintManager, userId)
|
||||
renameFingerprintsInteractorUnderTest =
|
||||
RenameFingerprintsInteractorImpl(fingerprintManager, userId, backgroundDispatcher)
|
||||
authenticateInteractorImplUnderTest = AuthenticateInteractorImpl(fingerprintManager, userId)
|
||||
|
||||
canEnrollFingerprintsInteractorUnderTest =
|
||||
CanEnrollFingerprintsInteractorImpl(fingerprintEnrollmentRepository)
|
||||
|
||||
enrollInteractorUnderTest = EnrollFingerprintInteractorImpl(userId, fingerprintManager, flow)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -119,7 +164,8 @@ class FingerprintManagerInteractorTest {
|
||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(emptyList())
|
||||
|
||||
val emptyFingerprintList: List<Fingerprint> = emptyList()
|
||||
assertThat(underTest.enrolledFingerprints.last()).isEqualTo(emptyFingerprintList)
|
||||
assertThat(enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last())
|
||||
.isEqualTo(emptyFingerprintList)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +175,7 @@ class FingerprintManagerInteractorTest {
|
||||
val fingerprintList: List<Fingerprint> = listOf(expected)
|
||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
|
||||
|
||||
val list = underTest.enrolledFingerprints.last()
|
||||
val list = enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last()
|
||||
assertThat(list!!.size).isEqualTo(fingerprintList.size)
|
||||
val actual = list[0]
|
||||
assertThat(actual.name).isEqualTo(expected.name)
|
||||
@@ -138,24 +184,51 @@ class FingerprintManagerInteractorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanEnrollFingerprint() =
|
||||
fun testCanEnrollFingerprintSucceeds() =
|
||||
testScope.runTest {
|
||||
val fingerprintList1: List<Fingerprint> =
|
||||
val fingerprintList: List<Fingerprint> =
|
||||
listOf(
|
||||
Fingerprint("Finger 1,", 2, 3L),
|
||||
Fingerprint("Finger 2,", 3, 3L),
|
||||
Fingerprint("Finger 3,", 4, 3L),
|
||||
Fingerprint("Finger 1", 2, 3L),
|
||||
Fingerprint("Finger 2", 3, 3L),
|
||||
Fingerprint("Finger 3", 4, 3L),
|
||||
)
|
||||
val fingerprintList2: List<Fingerprint> =
|
||||
fingerprintList1.plus(
|
||||
listOf(Fingerprint("Finger 4,", 5, 3L), Fingerprint("Finger 5,", 6, 3L))
|
||||
)
|
||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt()))
|
||||
.thenReturn(fingerprintList1)
|
||||
.thenReturn(fingerprintList2)
|
||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
|
||||
|
||||
assertThat(underTest.canEnrollFingerprints.last()).isTrue()
|
||||
assertThat(underTest.canEnrollFingerprints.last()).isFalse()
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch {
|
||||
canEnrollFingerprintsInteractorUnderTest.canEnrollFingerprints.collect { result = it }
|
||||
}
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
|
||||
assertThat(result).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanEnrollFingerprintFails() =
|
||||
testScope.runTest {
|
||||
val fingerprintList: List<Fingerprint> =
|
||||
listOf(
|
||||
Fingerprint("Finger 1", 2, 3L),
|
||||
Fingerprint("Finger 2", 3, 3L),
|
||||
Fingerprint("Finger 3", 4, 3L),
|
||||
Fingerprint("Finger 4", 5, 3L),
|
||||
Fingerprint("Finger 5", 6, 3L),
|
||||
)
|
||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
|
||||
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch {
|
||||
canEnrollFingerprintsInteractorUnderTest.canEnrollFingerprints.collect { result = it }
|
||||
}
|
||||
|
||||
runCurrent()
|
||||
job.cancelAndJoin()
|
||||
|
||||
assertThat(result).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -178,7 +251,8 @@ class FingerprintManagerInteractorTest {
|
||||
argumentCaptor()
|
||||
|
||||
var result: Pair<Long, ByteArray?>? = null
|
||||
val job = testScope.launch { result = underTest.generateChallenge(1L) }
|
||||
val job =
|
||||
testScope.launch { result = generateChallengeInteractorUnderTest.generateChallenge(1L) }
|
||||
runCurrent()
|
||||
|
||||
verify(fingerprintManager).generateChallenge(anyInt(), capture(generateChallengeCallback))
|
||||
@@ -201,7 +275,10 @@ class FingerprintManagerInteractorTest {
|
||||
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
|
||||
testScope.launch {
|
||||
result =
|
||||
removeFingerprintsInteractorUnderTest.removeFingerprint(fingerprintViewModelToRemove)
|
||||
}
|
||||
runCurrent()
|
||||
|
||||
verify(fingerprintManager)
|
||||
@@ -224,7 +301,10 @@ class FingerprintManagerInteractorTest {
|
||||
|
||||
var result: Boolean? = null
|
||||
val job =
|
||||
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
|
||||
testScope.launch {
|
||||
result =
|
||||
removeFingerprintsInteractorUnderTest.removeFingerprint(fingerprintViewModelToRemove)
|
||||
}
|
||||
runCurrent()
|
||||
|
||||
verify(fingerprintManager)
|
||||
@@ -246,7 +326,7 @@ class FingerprintManagerInteractorTest {
|
||||
testScope.runTest {
|
||||
val fingerprintToRename = FingerprintData("Finger 2", 1, 2L)
|
||||
|
||||
underTest.renameFingerprint(fingerprintToRename, "Woo")
|
||||
renameFingerprintsInteractorUnderTest.renameFingerprint(fingerprintToRename, "Woo")
|
||||
|
||||
verify(fingerprintManager).rename(eq(fingerprintToRename.fingerId), anyInt(), safeEq("Woo"))
|
||||
}
|
||||
@@ -257,7 +337,7 @@ class FingerprintManagerInteractorTest {
|
||||
val fingerprint = Fingerprint("Woooo", 100, 101L)
|
||||
|
||||
var result: FingerprintAuthAttemptModel? = null
|
||||
val job = launch { result = underTest.authenticate() }
|
||||
val job = launch { result = authenticateInteractorImplUnderTest.authenticate() }
|
||||
|
||||
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> = argumentCaptor()
|
||||
|
||||
@@ -284,7 +364,7 @@ class FingerprintManagerInteractorTest {
|
||||
fun testAuth_lockout() =
|
||||
testScope.runTest {
|
||||
var result: FingerprintAuthAttemptModel? = null
|
||||
val job = launch { result = underTest.authenticate() }
|
||||
val job = launch { result = authenticateInteractorImplUnderTest.authenticate() }
|
||||
|
||||
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> = argumentCaptor()
|
||||
|
||||
@@ -314,7 +394,7 @@ class FingerprintManagerInteractorTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollState? = null
|
||||
val job = launch {
|
||||
underTest
|
||||
enrollInteractorUnderTest
|
||||
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||
.collect { result = it }
|
||||
}
|
||||
@@ -343,7 +423,7 @@ class FingerprintManagerInteractorTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollState? = null
|
||||
val job = launch {
|
||||
underTest
|
||||
enrollInteractorUnderTest
|
||||
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||
.collect { result = it }
|
||||
}
|
||||
@@ -372,7 +452,7 @@ class FingerprintManagerInteractorTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollState? = null
|
||||
val job = launch {
|
||||
underTest
|
||||
enrollInteractorUnderTest
|
||||
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||
.collect { result = it }
|
||||
}
|
||||
|
@@ -99,9 +99,10 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
backgroundViewModel.inForeground()
|
||||
enrollViewModel =
|
||||
FingerprintEnrollViewModel(
|
||||
fakeFingerprintManagerInteractor,
|
||||
gatekeeperViewModel,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
accessibilityInteractor =
|
||||
object : AccessibilityInteractor {
|
||||
|
@@ -49,8 +49,7 @@ class RFPSIconTouchViewModelTest {
|
||||
fun setup() {
|
||||
Dispatchers.setMain(backgroundDispatcher)
|
||||
testScope = TestScope(backgroundDispatcher)
|
||||
rfpsIconTouchViewModel =
|
||||
RFPSIconTouchViewModel()
|
||||
rfpsIconTouchViewModel = RFPSIconTouchViewModel()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@@ -88,9 +88,10 @@ class FingerprintEnrollEnrollingViewModelTest {
|
||||
backgroundViewModel.inForeground()
|
||||
val fingerprintEnrollViewModel =
|
||||
FingerprintEnrollViewModel(
|
||||
fakeFingerprintManagerInteractor,
|
||||
gateKeeperViewModel,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
enrollEnrollingViewModel =
|
||||
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
||||
|
@@ -67,10 +67,11 @@ class FingerprintSettingsNavigationViewModelTest {
|
||||
underTest =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
null,
|
||||
null,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
}
|
||||
@@ -272,10 +273,11 @@ class FingerprintSettingsNavigationViewModelTest {
|
||||
underTest =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
|
||||
@@ -299,10 +301,11 @@ class FingerprintSettingsNavigationViewModelTest {
|
||||
underTest =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
|
||||
@@ -331,10 +334,11 @@ class FingerprintSettingsNavigationViewModelTest {
|
||||
underTest =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
|
||||
|
@@ -73,19 +73,25 @@ class FingerprintSettingsViewModelTest {
|
||||
navigationViewModel =
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
null,
|
||||
null,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsNavigationViewModel::class.java)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
}
|
||||
@@ -114,14 +120,7 @@ class FingerprintSettingsViewModelTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintData("a", 1, 3L))
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptModel? = null
|
||||
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
|
||||
@@ -156,14 +155,7 @@ class FingerprintSettingsViewModelTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintData("a", 1, 3L))
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptModel? = null
|
||||
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
|
||||
@@ -198,14 +190,7 @@ class FingerprintSettingsViewModelTest {
|
||||
val success = FingerprintAuthAttemptModel.Success(1)
|
||||
fakeFingerprintManagerInteractor.authenticateAttempt = success
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var authAttempt: FingerprintAuthAttemptModel? = null
|
||||
|
||||
@@ -225,14 +210,7 @@ class FingerprintSettingsViewModelTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(fingerprintToDelete)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var dialog: PreferenceViewModel? = null
|
||||
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
|
||||
@@ -261,14 +239,7 @@ class FingerprintSettingsViewModelTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(fingerprintToRename)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var dialog: PreferenceViewModel? = null
|
||||
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
|
||||
@@ -299,14 +270,7 @@ class FingerprintSettingsViewModelTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(fingerprintToDelete)
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
var dialog: PreferenceViewModel? = null
|
||||
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
|
||||
@@ -390,6 +354,22 @@ class FingerprintSettingsViewModelTest {
|
||||
assertThat(authAttempt).isEqualTo(null)
|
||||
}
|
||||
|
||||
private fun recreateSettingsViewModel() {
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
}
|
||||
|
||||
private fun setupAuth(): MutableList<FingerprintData> {
|
||||
fakeFingerprintManagerInteractor.sensorProp =
|
||||
FingerprintSensorPropertiesInternal(
|
||||
@@ -409,14 +389,7 @@ class FingerprintSettingsViewModelTest {
|
||||
val success = FingerprintAuthAttemptModel.Success(1)
|
||||
fakeFingerprintManagerInteractor.authenticateAttempt = success
|
||||
|
||||
underTest =
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
defaultUserId,
|
||||
fakeFingerprintManagerInteractor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
.create(FingerprintSettingsViewModel::class.java)
|
||||
recreateSettingsViewModel()
|
||||
|
||||
return fingerprints
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_RESTRICTED
|
||||
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNKNOWN
|
||||
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED
|
||||
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils.UNLIMITED_EXPIRE_TIME
|
||||
import com.android.settings.testutils.FakeFeatureFactory
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -51,9 +52,14 @@ class AppOptModeSharedPreferencesUtilsTest {
|
||||
@Spy
|
||||
private var testBatteryOptimizeUtils = spy(BatteryOptimizeUtils(context, UID, PACKAGE_NAME))
|
||||
|
||||
private lateinit var featureFactory: FakeFeatureFactory
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
AppOptModeSharedPreferencesUtils.clearAll(context)
|
||||
featureFactory = FakeFeatureFactory.setupForTest()
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled)
|
||||
.thenReturn(false)
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -77,8 +83,17 @@ class AppOptModeSharedPreferencesUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAppOptModeExpirationInternal_withExpirationTime_verifyData() {
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L)
|
||||
fun updateAppOptModeExpirationInternal_withoutExpirationTime_verifyEmptyList() {
|
||||
insertAppOptModeEventForTest(expirationTime = UNLIMITED_EXPIRE_TIME)
|
||||
|
||||
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAppOptModeExpirationInternal_setOptimizedModeWithFlagEnabled_verifyData() {
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled)
|
||||
.thenReturn(true)
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_OPTIMIZED)
|
||||
|
||||
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||
|
||||
@@ -93,8 +108,46 @@ class AppOptModeSharedPreferencesUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAppOptModeExpirationInternal_withoutExpirationTime_verifyEmptyList() {
|
||||
insertAppOptModeEventForTest(expirationTime = UNLIMITED_EXPIRE_TIME)
|
||||
fun updateAppOptModeExpirationInternal_setOptimizedModeWithFlagDisabled_verifyData() {
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled)
|
||||
.thenReturn(false)
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_OPTIMIZED)
|
||||
|
||||
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||
|
||||
assertThat(events).hasSize(1)
|
||||
assertAppOptimizationModeEventInfo(
|
||||
events[0],
|
||||
UID,
|
||||
PACKAGE_NAME,
|
||||
MODE_OPTIMIZED,
|
||||
expirationTime = 1000L
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAppOptModeExpirationInternal_setRestrictedModeWithFlagEnabled_verifyData() {
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled)
|
||||
.thenReturn(true)
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_RESTRICTED)
|
||||
|
||||
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||
|
||||
assertThat(events).hasSize(1)
|
||||
assertAppOptimizationModeEventInfo(
|
||||
events[0],
|
||||
UID,
|
||||
PACKAGE_NAME,
|
||||
MODE_RESTRICTED,
|
||||
expirationTime = 1000L
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAppOptModeExpirationInternal_setRestrictedModeWithFlagDisabled_verifyEmptyList() {
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled)
|
||||
.thenReturn(false)
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_RESTRICTED)
|
||||
|
||||
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||
}
|
||||
@@ -126,6 +179,20 @@ class AppOptModeSharedPreferencesUtilsTest {
|
||||
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetExpiredAppOptModeBeforeTimestamp_forceExpiredData_verifyEmptyList() {
|
||||
whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled)
|
||||
.thenReturn(true)
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L)
|
||||
|
||||
AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp(
|
||||
context,
|
||||
queryTimestampMs = 999L
|
||||
)
|
||||
|
||||
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetExpiredAppOptModeBeforeTimestamp_noExpiredData_verifyData() {
|
||||
insertAppOptModeEventForTest(expirationTime = 1000L)
|
||||
@@ -217,14 +284,14 @@ class AppOptModeSharedPreferencesUtilsTest {
|
||||
assertThat(currentOptMode).isEqualTo(MODE_RESTRICTED)
|
||||
}
|
||||
|
||||
private fun insertAppOptModeEventForTest(expirationTime: Long) {
|
||||
private fun insertAppOptModeEventForTest(expirationTime: Long, mode: Int = MODE_OPTIMIZED) {
|
||||
whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true)
|
||||
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true)).thenReturn(MODE_OPTIMIZED)
|
||||
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true)).thenReturn(mode)
|
||||
AppOptModeSharedPreferencesUtils.updateAppOptModeExpirationInternal(
|
||||
context,
|
||||
mutableListOf(UID),
|
||||
mutableListOf(PACKAGE_NAME),
|
||||
mutableListOf(MODE_OPTIMIZED),
|
||||
mutableListOf(mode),
|
||||
longArrayOf(expirationTime),
|
||||
) { _: Int, _: String ->
|
||||
testBatteryOptimizeUtils
|
||||
|
@@ -17,13 +17,11 @@
|
||||
package com.android.settings.localepicker;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
@@ -66,14 +64,6 @@ public class TermsOfAddressCategoryControllerTest {
|
||||
Locale.setDefault(mCacheLocale);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_returnUnavailable() {
|
||||
Locale.setDefault(Locale.forLanguageTag("fr-CA"));
|
||||
|
||||
assertThat(mTermsOfAddressCategoryController.getAvailabilityStatus()).isEqualTo(
|
||||
CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_returnAvailable() {
|
||||
Locale.setDefault(Locale.forLanguageTag("fr-FR"));
|
||||
|
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static com.android.settings.network.InternetUpdater.INTERNET_NETWORKS_AVAILABLE;
|
||||
import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
|
||||
|
||||
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.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.NetworkScoreManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
import com.android.settings.wifi.WifiPickerTrackerHelper;
|
||||
import com.android.settings.wifi.WifiSummaryUpdater;
|
||||
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
|
||||
import com.android.wifitrackerlib.HotspotNetworkEntry;
|
||||
import com.android.wifitrackerlib.StandardWifiEntry;
|
||||
import com.android.wifitrackerlib.WifiPickerTracker;
|
||||
|
||||
import org.junit.Before;
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class InternetPreferenceControllerTest {
|
||||
|
||||
private static final String TEST_SUMMARY = "test summary";
|
||||
private static final String TEST_ALTERNATE_SUMMARY = "test alternate summary";
|
||||
private static final String NOT_CONNECTED = "Not connected";
|
||||
private static final String SUB_ID_1 = "1";
|
||||
private static final String SUB_ID_2 = "2";
|
||||
private static final String INVALID_SUB_ID = "-1";
|
||||
private static final String DISPLAY_NAME_1 = "Sub 1";
|
||||
private static final String DISPLAY_NAME_2 = "Sub 2";
|
||||
private static final String SUB_MCC_1 = "123";
|
||||
private static final String SUB_MNC_1 = "456";
|
||||
private static final String SUB_MCC_2 = "223";
|
||||
private static final String SUB_MNC_2 = "456";
|
||||
private static final String SUB_COUNTRY_ISO_1 = "Sub 1";
|
||||
private static final String SUB_COUNTRY_ISO_2 = "Sub 2";
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Spy
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
private SubscriptionInfoEntity mActiveSubInfo;
|
||||
@Mock
|
||||
private SubscriptionInfoEntity mDefaultDataSubInfo;
|
||||
@Mock
|
||||
private ConnectivityManager mConnectivityManager;
|
||||
@Mock
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
@Mock
|
||||
private WifiManager mWifiManager;
|
||||
@Mock
|
||||
private WifiSummaryUpdater mSummaryHelper;
|
||||
@Mock
|
||||
private WifiPickerTrackerHelper mWifiPickerTrackerHelper;
|
||||
@Mock
|
||||
private WifiPickerTracker mWifiPickerTracker;
|
||||
@Mock
|
||||
private HotspotNetworkEntry mHotspotNetworkEntry;
|
||||
|
||||
private LifecycleRegistry mLifecycleRegistry;
|
||||
|
||||
private MockInternetPreferenceController mController;
|
||||
private PreferenceScreen mScreen;
|
||||
private Preference mPreference;
|
||||
private List<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
|
||||
when(mContext.getSystemService(NetworkScoreManager.class))
|
||||
.thenReturn(mock(NetworkScoreManager.class));
|
||||
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
|
||||
when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
|
||||
when(mWifiPickerTrackerHelper.getWifiPickerTracker()).thenReturn(mWifiPickerTracker);
|
||||
when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(null /* WifiEntry */);
|
||||
when(mHotspotNetworkEntry.getAlternateSummary()).thenReturn(TEST_ALTERNATE_SUMMARY);
|
||||
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
|
||||
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
|
||||
mController = new MockInternetPreferenceController(mContext, mock(Lifecycle.class),
|
||||
mLifecycleOwner);
|
||||
mController.sIconMap.put(INTERNET_WIFI, 0);
|
||||
mController.mWifiPickerTrackerHelper = mWifiPickerTrackerHelper;
|
||||
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
mScreen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreference = new Preference(mContext);
|
||||
mPreference.setKey(InternetPreferenceController.KEY);
|
||||
mScreen.addPreference(mPreference);
|
||||
}
|
||||
|
||||
private class MockInternetPreferenceController extends
|
||||
com.android.settings.network.InternetPreferenceController {
|
||||
|
||||
private int mDefaultDataSubscriptionId;
|
||||
public MockInternetPreferenceController(Context context, Lifecycle lifecycle,
|
||||
LifecycleOwner lifecycleOwner) {
|
||||
super(context, lifecycle, lifecycleOwner);
|
||||
}
|
||||
|
||||
private List<SubscriptionInfoEntity> mSubscriptionInfoEntity;
|
||||
|
||||
@Override
|
||||
protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
|
||||
return mSubscriptionInfoEntity;
|
||||
}
|
||||
|
||||
public void setSubscriptionInfoList(List<SubscriptionInfoEntity> list) {
|
||||
mSubscriptionInfoEntity = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultDataSubscriptionId() {
|
||||
return mDefaultDataSubscriptionId;
|
||||
}
|
||||
|
||||
public void setDefaultDataSubscriptionId(int subscriptionId) {
|
||||
mDefaultDataSubscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, int slotId,
|
||||
int carrierId, String displayName, String mcc, String mnc, String countryIso,
|
||||
int cardId, boolean isVisible, boolean isValid, boolean isActive, boolean isAvailable,
|
||||
boolean isActiveData) {
|
||||
return new SubscriptionInfoEntity(subId, slotId, carrierId,
|
||||
displayName, displayName, 0, mcc, mnc, countryIso, false, cardId,
|
||||
TelephonyManager.DEFAULT_PORT_INDEX, false, null,
|
||||
SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, isVisible,
|
||||
"1234567890", true, false, isValid, true, isActive, isAvailable, isActiveData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldMatchPrefFlag() {
|
||||
assertThat(mController.isAvailable()).isEqualTo(
|
||||
mContext.getResources().getBoolean(R.bool.config_show_internet_settings));
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void onResume_shouldRegisterCallback() {
|
||||
mController.onResume();
|
||||
|
||||
verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
|
||||
any(int.class));
|
||||
verify(mConnectivityManager).registerNetworkCallback(
|
||||
any(NetworkRequest.class),
|
||||
any(ConnectivityManager.NetworkCallback.class),
|
||||
any(Handler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void onPause_shouldUnregisterCallback() {
|
||||
mController.onResume();
|
||||
mController.onPause();
|
||||
|
||||
verify(mContext, times(2)).unregisterReceiver(any(BroadcastReceiver.class));
|
||||
verify(mConnectivityManager, times(2)).unregisterNetworkCallback(
|
||||
any(ConnectivityManager.NetworkCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSummaryChanged_internetWifi_updateSummary() {
|
||||
when(mSummaryHelper.getSummary()).thenReturn(TEST_SUMMARY);
|
||||
mController.mSummaryHelper = mSummaryHelper;
|
||||
mController.onInternetTypeChanged(INTERNET_WIFI);
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
mController.onSummaryChanged(TEST_SUMMARY);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(TEST_SUMMARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSummaryChanged_internetNetworksAvailable_notUpdateSummary() {
|
||||
when(mSummaryHelper.getSummary()).thenReturn(TEST_SUMMARY);
|
||||
mController.mSummaryHelper = mSummaryHelper;
|
||||
mController.onInternetTypeChanged(INTERNET_NETWORKS_AVAILABLE);
|
||||
mController.displayPreference(mScreen);
|
||||
mPreference.setSummary(NOT_CONNECTED);
|
||||
|
||||
mController.onSummaryChanged(TEST_SUMMARY);
|
||||
|
||||
assertThat(mPreference.getSummary()).isNotEqualTo(TEST_SUMMARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateCellularSummary_getNullSubscriptionInfo_shouldNotCrash() {
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
|
||||
mController.updateCellularSummary();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateCellularSummary_getActiveSubscriptionInfo_cbrs() {
|
||||
mController.setDefaultDataSubscriptionId(Integer.parseInt(SUB_ID_2));
|
||||
mActiveSubInfo = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, false, true, true, true, true);
|
||||
mDefaultDataSubInfo = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
|
||||
SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, false, true, true, true, false);
|
||||
mSubscriptionInfoEntityList.add(mActiveSubInfo);
|
||||
mSubscriptionInfoEntityList.add(mDefaultDataSubInfo);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
mController.updateCellularSummary();
|
||||
assertThat(mPreference.getSummary()).isEqualTo(DISPLAY_NAME_2);
|
||||
|
||||
mActiveSubInfo = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true, true, true);
|
||||
mSubscriptionInfoEntityList.add(mActiveSubInfo);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
mController.onAvailableSubInfoChanged(mSubscriptionInfoEntityList);
|
||||
final String expectedSummary =
|
||||
ResourcesUtils.getResourcesString(mContext, "mobile_data_temp_using",
|
||||
DISPLAY_NAME_1);
|
||||
mController.updateCellularSummary();
|
||||
assertThat(mPreference.getSummary()).isEqualTo(expectedSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateHotspotNetwork_isHotspotNetworkEntry_updateAlternateSummary() {
|
||||
when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(mHotspotNetworkEntry);
|
||||
mController.onInternetTypeChanged(INTERNET_WIFI);
|
||||
mController.displayPreference(mScreen);
|
||||
mPreference.setSummary(TEST_SUMMARY);
|
||||
|
||||
mController.updateHotspotNetwork();
|
||||
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(TEST_ALTERNATE_SUMMARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateHotspotNetwork_notHotspotNetworkEntry_notChangeSummary() {
|
||||
when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(mock(StandardWifiEntry.class));
|
||||
mController.onInternetTypeChanged(INTERNET_WIFI);
|
||||
mController.displayPreference(mScreen);
|
||||
mPreference.setSummary(TEST_SUMMARY);
|
||||
|
||||
mController.updateHotspotNetwork();
|
||||
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(TEST_SUMMARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateHotspotNetwork_hotspotNetworkNotEnabled_returnFalse() {
|
||||
mController.mWifiPickerTrackerHelper = null;
|
||||
|
||||
assertThat(mController.updateHotspotNetwork()).isFalse();
|
||||
}
|
||||
}
|
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.network;
|
||||
|
||||
import static androidx.lifecycle.Lifecycle.Event;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MobileNetworkPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
@Mock
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private LifecycleRegistry mLifecycleRegistry;
|
||||
private MobileNetworkPreferenceController mController;
|
||||
private Preference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
mPreference = new Preference(mContext);
|
||||
mPreference.setKey(MobileNetworkPreferenceController.KEY_MOBILE_NETWORK_SETTINGS);
|
||||
|
||||
mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
|
||||
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secondaryUser_prefIsNotAvailable() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(false);
|
||||
when(mTelephonyManager.isDataCapable()).thenReturn(true);
|
||||
|
||||
mController = new MobileNetworkPreferenceController(mContext);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wifiOnly_prefIsNotAvailable() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
when(mTelephonyManager.isDataCapable()).thenReturn(false);
|
||||
|
||||
mController = new MobileNetworkPreferenceController(mContext);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void goThroughLifecycle_isAvailable_shouldListenToServiceChange() {
|
||||
mController = spy(new MobileNetworkPreferenceController(mContext));
|
||||
mLifecycleRegistry.addObserver(mController);
|
||||
doReturn(true).when(mController).isAvailable();
|
||||
|
||||
mLifecycleRegistry.handleLifecycleEvent(Event.ON_START);
|
||||
verify(mController).onStart();
|
||||
verify(mTelephonyManager).registerTelephonyCallback(
|
||||
mContext.getMainExecutor(), mController.mTelephonyCallback);
|
||||
|
||||
mLifecycleRegistry.handleLifecycleEvent(Event.ON_STOP);
|
||||
verify(mController).onStop();
|
||||
verify(mTelephonyManager).unregisterTelephonyCallback(mController.mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void serviceStateChange_shouldUpdatePrefSummary() {
|
||||
final String testCarrierName = "test";
|
||||
|
||||
mController = spy(new MobileNetworkPreferenceController(mContext));
|
||||
mLifecycleRegistry.addObserver(mController);
|
||||
doReturn(true).when(mController).isAvailable();
|
||||
|
||||
mScreen.addPreference(mPreference);
|
||||
|
||||
// Display pref and go through lifecycle to set up listener.
|
||||
mController.displayPreference(mScreen);
|
||||
mLifecycleRegistry.handleLifecycleEvent(Event.ON_START);
|
||||
verify(mController).onStart();
|
||||
verify(mTelephonyManager).registerTelephonyCallback(
|
||||
mContext.getMainExecutor(), mController.mTelephonyCallback);
|
||||
|
||||
doReturn(testCarrierName).when(mController).getSummary();
|
||||
|
||||
mController.mTelephonyCallback.onServiceStateChanged(null);
|
||||
|
||||
// Carrier name should be set.
|
||||
Assert.assertEquals(mPreference.getSummary(), testCarrierName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void airplaneModeTurnedOn_shouldDisablePreference() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Global.AIRPLANE_MODE_ON, 1);
|
||||
mController = spy(new MobileNetworkPreferenceController(mContext));
|
||||
final RestrictedPreference mPreference = new RestrictedPreference(mContext);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void airplaneModeTurnedOffAndNoUserRestriction_shouldEnablePreference() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Global.AIRPLANE_MODE_ON, 0);
|
||||
mController = spy(new MobileNetworkPreferenceController(mContext));
|
||||
final RestrictedPreference mPreference = new RestrictedPreference(mContext);
|
||||
mPreference.setDisabledByAdmin(null);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void airplaneModeTurnedOffAndHasUserRestriction_shouldDisablePreference() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Global.AIRPLANE_MODE_ON, 0);
|
||||
mController = spy(new MobileNetworkPreferenceController(mContext));
|
||||
final RestrictedPreference mPreference = new RestrictedPreference(mContext);
|
||||
mPreference.setDisabledByAdmin(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
@@ -54,11 +55,11 @@ public class NetworkProviderCallsSmsFragmentTest {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_IS_DUAL_SIM_ONBOARDING_ENABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@DisableFlags(Flags.FLAG_IS_DUAL_SIM_ONBOARDING_ENABLED)
|
||||
public void isPageSearchEnabled_shouldIncludeFragmentXml() {
|
||||
mPreferenceKeyList =
|
||||
NetworkProviderCallsSmsFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||
|
@@ -28,7 +28,6 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
@@ -63,12 +62,6 @@ public class NetworkProviderSimListControllerTest {
|
||||
private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category";
|
||||
private static final String DISPLAY_NAME_1 = "Sub 1";
|
||||
private static final String DISPLAY_NAME_2 = "Sub 2";
|
||||
private static final String SUB_MCC_1 = "123";
|
||||
private static final String SUB_MNC_1 = "456";
|
||||
private static final String SUB_MCC_2 = "223";
|
||||
private static final String SUB_MNC_2 = "456";
|
||||
private static final String SUB_COUNTRY_ISO_1 = "Sub 1";
|
||||
private static final String SUB_COUNTRY_ISO_2 = "Sub 2";
|
||||
|
||||
@Mock
|
||||
private SubscriptionInfoEntity mSubInfo1;
|
||||
@@ -140,12 +133,9 @@ public class NetworkProviderSimListControllerTest {
|
||||
}
|
||||
|
||||
private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, int slotId,
|
||||
int carrierId, String displayName, String mcc, String mnc, String countryIso,
|
||||
int cardId, boolean isValid, boolean isActive, boolean isAvailable) {
|
||||
return new SubscriptionInfoEntity(subId, slotId, carrierId, displayName, displayName, 0,
|
||||
mcc, mnc, countryIso, false, cardId, TelephonyManager.DEFAULT_PORT_INDEX, false,
|
||||
null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false,
|
||||
"1234567890", true, false, isValid, true, isActive, isAvailable, false);
|
||||
String displayName, boolean isValid, boolean isActive) {
|
||||
return new SubscriptionInfoEntity(subId, slotId, false, false, displayName, false,
|
||||
false, isValid, isActive, false);
|
||||
}
|
||||
|
||||
private String setSummaryResId(String resName, String value) {
|
||||
@@ -159,8 +149,7 @@ public class NetworkProviderSimListControllerTest {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void getSummary_tapToActivePSim() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, false, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1, true, false);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
displayPreferenceWithLifecycle();
|
||||
@@ -172,8 +161,7 @@ public class NetworkProviderSimListControllerTest {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void getSummary_inactivePSim() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, false, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1, true, false);
|
||||
doReturn(true).when(mSubscriptionManager).canDisablePhysicalSubscription();
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
@@ -187,8 +175,7 @@ public class NetworkProviderSimListControllerTest {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void getSummary_defaultCalls() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1, true, true);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
|
||||
@@ -209,8 +196,7 @@ public class NetworkProviderSimListControllerTest {
|
||||
defaultConfig.append(setSummaryResId("default_active_sim_calls"))
|
||||
.append(", ")
|
||||
.append(setSummaryResId("default_active_sim_sms"));
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1, true, true);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
|
||||
@@ -228,10 +214,8 @@ public class NetworkProviderSimListControllerTest {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void getAvailablePhysicalSubscription_withTwoPhysicalSims_returnTwo() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
|
||||
SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
|
||||
SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1, true, true);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, DISPLAY_NAME_2, true, true);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
|
||||
|
@@ -38,8 +38,6 @@ import android.telephony.UiccSlotMapping;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -47,7 +45,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@@ -81,25 +78,6 @@ public class UiccSlotUtilTest {
|
||||
when(mSubscriptionManager.getAllSubscriptionInfoList()).thenReturn(mSubscriptionInfoList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlotInfos_oneSimSlotDevice_returnTheCorrectSlotInfoList() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(oneSimSlotDeviceActivePsim());
|
||||
ImmutableList<UiccSlotInfo> testUiccSlotInfos =
|
||||
UiccSlotUtil.getSlotInfos(mTelephonyManager);
|
||||
|
||||
assertThat(testUiccSlotInfos.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlotInfos_twoSimSlotsDevice_returnTheCorrectSlotInfoList() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceActivePsimActiveEsim());
|
||||
ImmutableList<UiccSlotInfo> testUiccSlotInfos =
|
||||
UiccSlotUtil.getSlotInfos(mTelephonyManager);
|
||||
|
||||
assertThat(testUiccSlotInfos.size()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot0_returnTheCorrectEsimSlot() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
@@ -643,105 +621,7 @@ public class UiccSlotUtilTest {
|
||||
assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_noPsim_returnsFalse() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
oneSimSlotDeviceActiveEsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_activeRemovableEsimAndInactivePsim_returnsFalse() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceActiveRemovableEsimInactivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_activeRemovableEsimAndActivePsim_returnsTrue() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceActivePsimActiveRemovableEsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_inactiveRemovableEsimAndActivePsim_returnsTrue() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceInactiveRemovableEsimActivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_twoActiveRemovableEsimsAndInactivePsim_returnsFalse() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceTwoActiveRemovableEsimsInactivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_oneActiveOneInactiveRemovableEsimActivePsim_returnsTrue() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceOneActiveOneInactiveRemovableEsimsActivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_activePsim_returnsTrue() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
oneSimSlotDeviceActivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_inactivePsim_returnsFalse() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
oneSimSlotDeviceinactivePsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_activeEsimAndActivePsim_returnsTrue() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceActivePsimActiveEsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRemovableSimEnabled_activeEsimAndInactivePsim_returnsFalse() {
|
||||
when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
|
||||
twoSimSlotsDeviceInactivePsimActiveEsim());
|
||||
|
||||
boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
|
||||
|
||||
assertThat(testSlot).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performSwitchToSlot_setSimSlotMapping() throws UiccSlotsException {
|
||||
@@ -856,13 +736,6 @@ public class UiccSlotUtilTest {
|
||||
return slotMap;
|
||||
}
|
||||
|
||||
private List<UiccSlotMapping> createUiccSlotMappingSsModeEsimPort1Active() {
|
||||
List<UiccSlotMapping> slotMap = new ArrayList<>();
|
||||
slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0));
|
||||
|
||||
return slotMap;
|
||||
}
|
||||
|
||||
private List<UiccSlotMapping> createUiccSlotMappingPsimAndPort0() {
|
||||
List<UiccSlotMapping> slotMap = new ArrayList<>();
|
||||
slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0));
|
||||
@@ -915,14 +788,6 @@ public class UiccSlotUtilTest {
|
||||
return new UiccSlotInfo[]{createUiccSlotInfo(false, true, 0, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] oneSimSlotDeviceActiveEsim() {
|
||||
return new UiccSlotInfo[]{createUiccSlotInfo(true, false, 1, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] oneSimSlotDeviceinactivePsim() {
|
||||
return new UiccSlotInfo[]{createUiccSlotInfo(false, true, -1, false)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceActivePsimActiveEsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(false, true, 0, true),
|
||||
@@ -941,61 +806,12 @@ public class UiccSlotUtilTest {
|
||||
createUiccSlotInfo(true, true, 1, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceActiveRemovableEsimInactivePsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(true, true, 0, true),
|
||||
createUiccSlotInfo(false, true, -1, false)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceInactiveRemovableEsimActivePsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(true, true, -1, false),
|
||||
createUiccSlotInfo(false, true, 0, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceTwoActiveRemovableEsimsInactivePsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfoForRemovableEsimMep(0, true, 1, true),
|
||||
createUiccSlotInfo(false, true, -1, false)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceOneActiveOneInactiveRemovableEsimsActivePsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfoForRemovableEsimMep(1, true, -1, false),
|
||||
createUiccSlotInfo(false, true, 0, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceActiveEsimActivePsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(true, false, 0, true),
|
||||
createUiccSlotInfo(false, true, 1, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceTwoActiveEsims() {
|
||||
// device supports MEP, so device can enable two esims.
|
||||
// If device has psim slot, the UiccSlotInfo of psim always be in UiccSlotInfo[].
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(false, true, -1, true),
|
||||
createUiccSlotInfoForEsimMep(0, true, 1, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceActivePsimInactiveEsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(false, true, 0, true),
|
||||
createUiccSlotInfo(true, false, -1, false)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceInactivePsimActiveEsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(false, true, 0, false),
|
||||
createUiccSlotInfo(true, false, 1, true)};
|
||||
}
|
||||
|
||||
private UiccSlotInfo[] twoSimSlotsDeviceNoInsertPsimActiveEsim() {
|
||||
return new UiccSlotInfo[]{
|
||||
createUiccSlotInfo(false, true, -1, false),
|
||||
createUiccSlotInfo(true, false, 1, true)};
|
||||
}
|
||||
//ToDo: add more cases.
|
||||
|
||||
private UiccSlotInfo createUiccSlotInfo(boolean isEuicc, boolean isRemovable,
|
||||
@@ -1011,36 +827,4 @@ public class UiccSlotUtilTest {
|
||||
logicalSlotIdx /* logicalSlotIdx */, isActive /* isActive */))
|
||||
);
|
||||
}
|
||||
|
||||
private UiccSlotInfo createUiccSlotInfoForEsimMep(int logicalSlotIdx1, boolean isActiveEsim1,
|
||||
int logicalSlotIdx2, boolean isActiveEsim2) {
|
||||
return new UiccSlotInfo(
|
||||
true, /* isEuicc */
|
||||
"123", /* cardId */
|
||||
CARD_STATE_INFO_PRESENT, /* cardStateInfo */
|
||||
true, /* isExtendApduSupported */
|
||||
false, /* isRemovable */
|
||||
Arrays.asList(
|
||||
new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
|
||||
logicalSlotIdx1 /* logicalSlotIdx */, isActiveEsim1 /* isActive */),
|
||||
new UiccPortInfo("" /* iccId */, 1 /* portIdx */,
|
||||
logicalSlotIdx2 /* logicalSlotIdx */,
|
||||
isActiveEsim2 /* isActive */)));
|
||||
}
|
||||
|
||||
private UiccSlotInfo createUiccSlotInfoForRemovableEsimMep(int logicalSlotIdx1,
|
||||
boolean isActiveEsim1, int logicalSlotIdx2, boolean isActiveEsim2) {
|
||||
return new UiccSlotInfo(
|
||||
true, /* isEuicc */
|
||||
"123", /* cardId */
|
||||
CARD_STATE_INFO_PRESENT, /* cardStateInfo */
|
||||
true, /* isExtendApduSupported */
|
||||
true, /* isRemovable */
|
||||
Arrays.asList(
|
||||
new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
|
||||
logicalSlotIdx1 /* logicalSlotIdx */, isActiveEsim1 /* isActive */),
|
||||
new UiccPortInfo("" /* iccId */, 1 /* portIdx */,
|
||||
logicalSlotIdx2 /* logicalSlotIdx */,
|
||||
isActiveEsim2 /* isActive */)));
|
||||
}
|
||||
}
|
||||
|
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.ims;
|
||||
|
||||
import android.content.Context;
|
||||
import android.telephony.ims.ImsException;
|
||||
|
||||
/**
|
||||
* Controller class for mock VT status
|
||||
*/
|
||||
public class MockVtQueryImsState extends VtQueryImsState {
|
||||
|
||||
private Boolean mIsTtyOnVolteEnabled;
|
||||
private Boolean mIsEnabledOnPlatform;
|
||||
private Boolean mIsProvisionedOnDevice;
|
||||
private Boolean mIsEnabledByUser;
|
||||
private Boolean mIsServiceStateReady;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context {@link Context}
|
||||
* @param subId subscription's id
|
||||
*/
|
||||
public MockVtQueryImsState(Context context, int subId) {
|
||||
super(context, subId);
|
||||
}
|
||||
|
||||
public void setIsTtyOnVolteEnabled(boolean enabled) {
|
||||
mIsTtyOnVolteEnabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTtyOnVolteEnabled(int subId) {
|
||||
if (mIsTtyOnVolteEnabled != null) {
|
||||
return mIsTtyOnVolteEnabled;
|
||||
}
|
||||
return super.isTtyOnVolteEnabled(subId);
|
||||
}
|
||||
|
||||
public void setIsEnabledByPlatform(boolean isEnabled) {
|
||||
mIsEnabledOnPlatform = isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEnabledByPlatform(int subId) throws InterruptedException, ImsException,
|
||||
IllegalArgumentException {
|
||||
if (mIsEnabledOnPlatform != null) {
|
||||
return mIsEnabledOnPlatform;
|
||||
}
|
||||
return super.isEnabledByPlatform(subId);
|
||||
}
|
||||
|
||||
public void setIsProvisionedOnDevice(boolean isProvisioned) {
|
||||
mIsProvisionedOnDevice = isProvisioned;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isProvisionedOnDevice(int subId) {
|
||||
if (mIsProvisionedOnDevice != null) {
|
||||
return mIsProvisionedOnDevice;
|
||||
}
|
||||
return super.isProvisionedOnDevice(subId);
|
||||
}
|
||||
|
||||
public void setServiceStateReady(boolean isReady) {
|
||||
mIsServiceStateReady = isReady;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isServiceStateReady(int subId) throws InterruptedException, ImsException,
|
||||
IllegalArgumentException {
|
||||
if (mIsServiceStateReady != null) {
|
||||
return mIsServiceStateReady;
|
||||
}
|
||||
return super.isServiceStateReady(subId);
|
||||
}
|
||||
|
||||
public void setIsEnabledByUser(boolean enabled) {
|
||||
mIsEnabledByUser = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEnabledByUser(int subId) {
|
||||
if (mIsEnabledByUser != null) {
|
||||
return mIsEnabledByUser;
|
||||
}
|
||||
return super.isEnabledByUser(subId);
|
||||
}
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.network.CarrierConfigCache;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CarrierSettingsVersionPreferenceControllerTest {
|
||||
@Mock
|
||||
private CarrierConfigCache mCarrierConfigCache;
|
||||
|
||||
private CarrierSettingsVersionPreferenceController mController;
|
||||
private int mSubscriptionId = 1234;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Context context = spy(ApplicationProvider.getApplicationContext());
|
||||
CarrierConfigCache.setTestInstance(context, mCarrierConfigCache);
|
||||
mController = new CarrierSettingsVersionPreferenceController(context, "mock_key");
|
||||
mController.init(mSubscriptionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_nullConfig_noCrash() {
|
||||
doReturn(null).when(mCarrierConfigCache).getConfigForSubId(mSubscriptionId);
|
||||
|
||||
assertThat(mController.getSummary()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_nullVersionString_noCrash() {
|
||||
doReturn(new PersistableBundle()).when(mCarrierConfigCache)
|
||||
.getConfigForSubId(mSubscriptionId);
|
||||
assertThat(mController.getSummary()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasVersionString_correctSummary() {
|
||||
final PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putString(CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING,
|
||||
"test_version_123");
|
||||
doReturn(bundle).when(mCarrierConfigCache).getConfigForSubId(mSubscriptionId);
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("test_version_123");
|
||||
}
|
||||
}
|
@@ -30,7 +30,6 @@ import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
@@ -70,15 +69,6 @@ public class DefaultSubscriptionControllerTest {
|
||||
private static final String DISPLAY_NAME_1 = "Sub 1";
|
||||
private static final String DISPLAY_NAME_2 = "Sub 2";
|
||||
private static final String DISPLAY_NAME_3 = "Sub 3";
|
||||
private static final String SUB_MCC_1 = "123";
|
||||
private static final String SUB_MNC_1 = "456";
|
||||
private static final String SUB_MCC_2 = "223";
|
||||
private static final String SUB_MNC_2 = "456";
|
||||
private static final String SUB_MCC_3 = "323";
|
||||
private static final String SUB_MNC_3 = "456";
|
||||
private static final String SUB_COUNTRY_ISO_1 = "Sub 1";
|
||||
private static final String SUB_COUNTRY_ISO_2 = "Sub 2";
|
||||
private static final String SUB_COUNTRY_ISO_3 = "Sub 3";
|
||||
|
||||
@Mock
|
||||
private SubscriptionManager mSubMgr;
|
||||
@@ -133,12 +123,9 @@ public class DefaultSubscriptionControllerTest {
|
||||
SubscriptionUtil.setActiveSubscriptionsForTesting(null);
|
||||
}
|
||||
|
||||
private SubscriptionInfoEntity setupSubscriptionInfoEntity(
|
||||
String subId, String displayName, String mcc, String mnc, String countryIso) {
|
||||
return new SubscriptionInfoEntity(subId, 1, 1, displayName, displayName, 0, mcc, mnc,
|
||||
countryIso, false, 1, TelephonyManager.DEFAULT_PORT_INDEX, false, null,
|
||||
SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false, "1234567890",
|
||||
true, false, true, true, true, true, false);
|
||||
private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, String displayName) {
|
||||
return new SubscriptionInfoEntity(subId, 1, false, false, displayName, false, false, true,
|
||||
true, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -151,8 +138,7 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void getSummary_singleSub() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mController.displayPreference(mScreen);
|
||||
@@ -164,10 +150,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void getSummary_twoSubs() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
@@ -180,10 +164,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_prefChangedToSub2_callbackCalledCorrectly() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
@@ -197,10 +179,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_prefChangedToAlwaysAsk_callbackCalledCorrectly() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
@@ -217,10 +197,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
@Test
|
||||
public void onPreferenceChange_prefBecomesAvailable_onPreferenceChangeCallbackNotNull() {
|
||||
// Start with only one sub active, so the pref is not available
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
@@ -240,10 +218,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void onSubscriptionsChanged_twoSubscriptionsDefaultChanges_selectedEntryGetsUpdated() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
@@ -261,10 +237,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void onSubscriptionsChanged_goFromTwoSubscriptionsToOne_prefDisappears() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
@@ -287,10 +261,8 @@ public class DefaultSubscriptionControllerTest {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void onSubscriptionsChanged_goFromOneSubscriptionToTwo_prefAppears() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mController.onActiveSubInfoChanged(mSubscriptionInfoEntityList);
|
||||
@@ -309,12 +281,9 @@ public class DefaultSubscriptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void onSubscriptionsChanged_goFromTwoToThreeSubscriptions_listGetsUpdated() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1,
|
||||
SUB_COUNTRY_ISO_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, SUB_MCC_2, SUB_MNC_2,
|
||||
SUB_COUNTRY_ISO_2);
|
||||
mSubInfo3 = setupSubscriptionInfoEntity(SUB_ID_3, DISPLAY_NAME_3, SUB_MCC_3, SUB_MNC_3,
|
||||
SUB_COUNTRY_ISO_3);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2);
|
||||
mSubInfo3 = setupSubscriptionInfoEntity(SUB_ID_3, DISPLAY_NAME_3);
|
||||
mController.setDefaultSubscription(Integer.parseInt(mSubInfo1.subId));
|
||||
mSubscriptionInfoEntityList.add(mSubInfo1);
|
||||
mSubscriptionInfoEntityList.add(mSubInfo2);
|
||||
|
@@ -18,9 +18,6 @@ package com.android.settings.network.telephony;
|
||||
|
||||
import static androidx.lifecycle.Lifecycle.Event.ON_START;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.android.settings.network.telephony.MobileNetworkUtils.getRafFromNetworkType;
|
||||
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
|
||||
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
|
||||
@@ -33,8 +30,6 @@ import static com.android.settings.network.telephony.TelephonyConstants.RadioAcc
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -123,79 +118,6 @@ public class EnabledNetworkModePreferenceControllerTest {
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() {
|
||||
mPersistableBundle.putBoolean(
|
||||
CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
|
||||
true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_hidePreferredNetworkType_returnUnavailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL,
|
||||
true);
|
||||
|
||||
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
|
||||
when(mServiceState.getDataRegistrationState()).thenReturn(
|
||||
ServiceState.STATE_OUT_OF_SERVICE);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
|
||||
when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
|
||||
when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
|
||||
|
||||
when(mServiceState.getRoaming()).thenReturn(false);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
|
||||
when(mServiceState.getRoaming()).thenReturn(true);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_carrierConfigNotReady_returnUnavailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_notWorldPhone_returnAvailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
|
||||
false);
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_callStateIsIdle_returnAvailable() {
|
||||
mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA);
|
||||
mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_IDLE);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
assertTrue(mPreference.isEnabled());
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void getAvailabilityStatus_duringCalling_returnAvailable() {
|
||||
mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA);
|
||||
mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
assertFalse(mPreference.isEnabled());
|
||||
}
|
||||
|
||||
@UiThreadTest
|
||||
@Test
|
||||
public void updateState_LteWorldPhone_GlobalHasLte() {
|
||||
|
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
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;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class EuiccPreferenceControllerTest {
|
||||
private static final int SUB_ID = 2;
|
||||
|
||||
@Mock private TelephonyManager mTelephonyManager;
|
||||
|
||||
private EuiccPreferenceController mController;
|
||||
private Preference mPreference;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
|
||||
|
||||
mPreference = new Preference(mContext);
|
||||
mController = new EuiccPreferenceController(mContext, "euicc");
|
||||
mController.init(SUB_ID);
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlePreferenceTreeClick_startActivity() {
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
doNothing().when(mContext).startActivity(captor.capture());
|
||||
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
assertThat(captor.getValue().getAction()).isEqualTo(
|
||||
EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
|
||||
}
|
||||
}
|
@@ -29,7 +29,6 @@ import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
@@ -75,8 +74,6 @@ public class MobileDataPreferenceControllerTest {
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo;
|
||||
@Mock
|
||||
private FragmentTransaction mFragmentTransaction;
|
||||
@Mock
|
||||
private Lifecycle mLifecycle;
|
||||
@@ -120,19 +117,15 @@ public class MobileDataPreferenceControllerTest {
|
||||
}
|
||||
|
||||
private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, String displayName,
|
||||
boolean isOpportunistic, boolean isValid, boolean isActive, boolean isAvailable) {
|
||||
boolean isOpportunistic, boolean isValid, boolean isActive) {
|
||||
int id = Integer.parseInt(subId);
|
||||
return new SubscriptionInfoEntity(subId, id, id,
|
||||
displayName, displayName, 0, "mcc", "mnc", "countryIso", false, id,
|
||||
TelephonyManager.DEFAULT_PORT_INDEX, isOpportunistic, null,
|
||||
SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false,
|
||||
"1234567890", true, false, isValid, true, isActive, isAvailable, false);
|
||||
return new SubscriptionInfoEntity(subId, id, false, isOpportunistic, displayName, false,
|
||||
false, isValid, isActive, false);
|
||||
}
|
||||
|
||||
private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId,
|
||||
boolean isDatEnabled) {
|
||||
return new MobileNetworkInfoEntity(subId, false, false, isDatEnabled, false, false, false,
|
||||
false, false, false, false, false);
|
||||
return new MobileNetworkInfoEntity(subId, isDatEnabled, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,7 +138,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void isDialogNeeded_disableSingleSim_returnFalse() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true);
|
||||
mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
doReturn(1).when(mTelephonyManager).getActiveModemCount();
|
||||
|
||||
@@ -154,12 +147,12 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true);
|
||||
mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
|
||||
doReturn(1).when(mTelephonyManager).getActiveModemCount();
|
||||
// Ideally, it would be better if we could set the default data subscription to
|
||||
// SUB_ID_OTHER, and set that as an active subscription id.
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, false, true, true, true);
|
||||
mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, false, true, true);
|
||||
mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
doReturn(2).when(mTelephonyManager).getActiveModemCount();
|
||||
|
||||
@@ -181,7 +174,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_singleSim_On_shouldEnableData() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true);
|
||||
mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
mController.setSubscriptionInfoEntity(mSubInfo1);
|
||||
mController.setMobileNetworkInfoEntity(mNetworkInfo1);
|
||||
@@ -195,7 +188,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_multiSim_On_shouldEnableData() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true);
|
||||
mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
mController.setSubscriptionInfoEntity(mSubInfo1);
|
||||
mController.setMobileNetworkInfoEntity(mNetworkInfo1);
|
||||
@@ -220,7 +213,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateState_opportunistic_disabled() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true);
|
||||
mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
@@ -232,7 +225,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateState_notOpportunistic_enabled() {
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true);
|
||||
mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true);
|
||||
mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
|
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.network.telephony;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
|
||||
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
|
||||
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
|
||||
@@ -32,7 +30,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -91,43 +88,6 @@ public class PreferredNetworkModePreferenceControllerTest {
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
|
||||
true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_worldPhone_returnAvailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
|
||||
false);
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hidePreferredNetworkType_returnUnavailable() {
|
||||
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL,
|
||||
true);
|
||||
|
||||
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
|
||||
when(mServiceState.getDataRegistrationState()).thenReturn(
|
||||
ServiceState.STATE_OUT_OF_SERVICE);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
|
||||
when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
|
||||
when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
|
||||
|
||||
when(mServiceState.getRoaming()).thenReturn(false);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
|
||||
when(mServiceState.getRoaming()).thenReturn(true);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_updateByNetworkMode() {
|
||||
// NETWORK_MODE_TDSCDMA_GSM_WCDMA = RAF_TD_SCDMA | GSM | WCDMA
|
||||
|
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class RoamingPreferenceControllerTest {
|
||||
private static final int SUB_ID = 2;
|
||||
|
||||
@Mock
|
||||
private FragmentManager mFragmentManager;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private TelephonyManager mInvalidTelephonyManager;
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
@Mock
|
||||
private FragmentTransaction mFragmentTransaction;
|
||||
@Mock
|
||||
private CarrierConfigManager mCarrierConfigManager;
|
||||
@Mock
|
||||
private Lifecycle mLifecycle;
|
||||
@Mock
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
|
||||
private LifecycleRegistry mLifecycleRegistry;
|
||||
private RoamingPreferenceController mController;
|
||||
private RestrictedSwitchPreference mPreference;
|
||||
private Context mContext;
|
||||
private MobileNetworkInfoEntity mMobileNetworkInfoEntity;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
|
||||
doReturn(mSubscriptionManager).when(mContext).getSystemService(
|
||||
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
|
||||
|
||||
doReturn(mCarrierConfigManager).when(mContext).getSystemService(
|
||||
Context.CARRIER_CONFIG_SERVICE);
|
||||
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
|
||||
doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
|
||||
|
||||
mPreference = spy(new RestrictedSwitchPreference(mContext));
|
||||
mController = spy(
|
||||
new RoamingPreferenceController(mContext, "roaming", mLifecycle, mLifecycleOwner,
|
||||
SUB_ID));
|
||||
mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
|
||||
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
|
||||
mController.init(mFragmentManager, SUB_ID, mMobileNetworkInfoEntity);
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
}
|
||||
|
||||
private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId,
|
||||
boolean isDataRoaming) {
|
||||
return new MobileNetworkInfoEntity(subId, false, false, true, false, false, false, false,
|
||||
false, false, false, isDataRoaming);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_validSubId_returnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_invalidSubId_returnUnsearchable() {
|
||||
mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
|
||||
mMobileNetworkInfoEntity);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus(
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDialogNeeded_roamingDisabledWithoutFlag_returnTrue() {
|
||||
final PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putBoolean(CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
|
||||
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
|
||||
mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
|
||||
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
|
||||
|
||||
assertThat(mController.isDialogNeeded()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDialogNeeded_roamingEnabled_returnFalse() {
|
||||
mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
|
||||
|
||||
assertThat(mController.isDialogNeeded()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void setChecked_needDialog_showDialog() {
|
||||
mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
|
||||
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
|
||||
doReturn(null).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
|
||||
|
||||
mController.setChecked(true);
|
||||
|
||||
verify(mFragmentManager).beginTransaction();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_invalidSubId_disabled() {
|
||||
mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(
|
||||
String.valueOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID), false);
|
||||
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
|
||||
mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
|
||||
mMobileNetworkInfoEntity);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_validSubId_enabled() {
|
||||
mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
|
||||
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_isNotDisabledByAdmin_shouldInvokeSetEnabled() {
|
||||
when(mPreference.isDisabledByAdmin()).thenReturn(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setEnabled(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_isDisabledByAdmin_shouldNotInvokeSetEnabled() {
|
||||
when(mPreference.isDisabledByAdmin()).thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference, never()).setEnabled(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_carrierConfigIsNull_shouldReturnAvailable() {
|
||||
doReturn(null).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_forceHomeNetworkIsFalse_shouldReturnAvailable() {
|
||||
final PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, false);
|
||||
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_forceHomeNetworkIsTrue_shouldReturnConditionallyAvailable() {
|
||||
final PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, true);
|
||||
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
}
|
@@ -339,6 +339,30 @@ public class SecuritySettingsTest {
|
||||
assertThat(mPreferenceCombined.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFace_isNotIndexable() throws Exception {
|
||||
when(mFaceManager.isHardwareDetected()).thenReturn(false);
|
||||
final BaseSearchIndexProvider indexProvider = SecuritySettings.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final List<String> allXmlKeys = TestUtils.getAllXmlKeys(mContext, indexProvider);
|
||||
final List<String> nonIndexableKeys = indexProvider.getNonIndexableKeys(mContext);
|
||||
allXmlKeys.removeAll(nonIndexableKeys);
|
||||
|
||||
assertThat(allXmlKeys).doesNotContain(SecuritySettings.KEY_FACE_SETTINGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFingerprint_isNotIndexable() throws Exception {
|
||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
|
||||
final BaseSearchIndexProvider indexProvider = SecuritySettings.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final List<String> allXmlKeys = TestUtils.getAllXmlKeys(mContext, indexProvider);
|
||||
final List<String> nonIndexableKeys = indexProvider.getNonIndexableKeys(mContext);
|
||||
allXmlKeys.removeAll(nonIndexableKeys);
|
||||
|
||||
assertThat(allXmlKeys).doesNotContain(SecuritySettings.KEY_FINGERPRINT_SETTINGS);
|
||||
}
|
||||
|
||||
boolean isFacePrefAvailable(List<AbstractPreferenceController> controllers) {
|
||||
return controllers.stream().filter(
|
||||
controller -> controller instanceof FaceStatusPreferenceController
|
||||
|
@@ -25,7 +25,6 @@ import com.android.settings.accounts.AccountFeatureProvider;
|
||||
import com.android.settings.applications.ApplicationFeatureProvider;
|
||||
import com.android.settings.biometrics.face.FaceFeatureProvider;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider;
|
||||
import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
|
||||
import com.android.settings.bluetooth.BluetoothFeatureProvider;
|
||||
import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider;
|
||||
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
|
||||
@@ -82,7 +81,6 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
|
||||
public final FaceFeatureProvider mFaceFeatureProvider;
|
||||
public final FingerprintFeatureProvider mFingerprintFeatureProvider;
|
||||
public final BiometricsRepositoryProvider mBiometricsRepositoryProvider;
|
||||
|
||||
public PanelFeatureProvider panelFeatureProvider;
|
||||
public SlicesFeatureProvider slicesFeatureProvider;
|
||||
@@ -140,7 +138,6 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
|
||||
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
|
||||
mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class);
|
||||
mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class);
|
||||
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
|
||||
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
|
||||
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
|
||||
@@ -272,11 +269,6 @@ public class FakeFeatureFactory extends FeatureFactory {
|
||||
return mFingerprintFeatureProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiometricsRepositoryProvider getBiometricsRepositoryProvider() {
|
||||
return mBiometricsRepositoryProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WifiTrackerLibProvider getWifiTrackerLibProvider() {
|
||||
return wifiTrackerLibProvider;
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.core.BasePreferenceController.AVAILABLE
|
||||
import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
|
||||
import com.android.wifitrackerlib.WifiEntry
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
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
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
class WepLessSecureWarningControllerTest {
|
||||
@get:Rule
|
||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
@Mock
|
||||
private lateinit var mockWifiEntry: WifiEntry
|
||||
|
||||
private val controller = WepLessSecureWarningController(context, TEST_KEY)
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_default_conditionallyUnavailable() {
|
||||
assertThat(controller.availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_noWepSecurityType_conditionallyUnavailable() {
|
||||
whenever(mockWifiEntry.securityTypes).thenReturn(listOf(WifiEntry.SECURITY_PSK))
|
||||
|
||||
controller.setWifiEntry(mockWifiEntry)
|
||||
|
||||
assertThat(controller.availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_containsWepSecurityType_available() {
|
||||
whenever(mockWifiEntry.securityTypes).thenReturn(listOf(WifiEntry.SECURITY_WEP))
|
||||
|
||||
controller.setWifiEntry(mockWifiEntry)
|
||||
|
||||
assertThat(controller.availabilityStatus).isEqualTo(AVAILABLE)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TEST_KEY = "test_key"
|
||||
}
|
||||
}
|
@@ -20,15 +20,33 @@ import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.wifi.factory.WifiFeatureProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -44,18 +62,36 @@ public class WifiDppConfiguratorActivityTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Spy
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private FragmentManager mFragmentManager;
|
||||
|
||||
// Mock, created by FakeFeatureFactory
|
||||
private WifiFeatureProvider mWifiFeatureProviderMock;
|
||||
|
||||
@Spy
|
||||
private WifiDppConfiguratorActivity mActivity;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
|
||||
mActivity = new WifiDppConfiguratorActivity();
|
||||
mActivity.mFragmentManager = mFragmentManager;
|
||||
doReturn(mContext).when(mActivity).getApplicationContext();
|
||||
|
||||
FragmentTransaction mockTransaction = mock(FragmentTransaction.class);
|
||||
when(mFragmentManager.beginTransaction()).thenReturn(mockTransaction);
|
||||
when(mockTransaction.replace(anyInt(), any(Fragment.class), anyString()))
|
||||
.thenReturn(mockTransaction);
|
||||
|
||||
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
|
||||
mWifiFeatureProviderMock = featureFactory.mWifiFeatureProvider;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,4 +107,37 @@ public class WifiDppConfiguratorActivityTest {
|
||||
|
||||
assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
|
||||
public void showQrCodeGeneratorFragment_shouldUseFeatureFactory() {
|
||||
when(mUserManager.isGuestUser()).thenReturn(false);
|
||||
when(mWifiFeatureProviderMock.getWifiDppQrCodeGeneratorFragment())
|
||||
.thenReturn(new WifiDppQrCodeGeneratorFragment());
|
||||
|
||||
mActivity.handleIntent(createQrCodeGeneratorIntent());
|
||||
|
||||
verify(mWifiFeatureProviderMock).getWifiDppQrCodeGeneratorFragment();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
|
||||
public void showQrCodeGeneratorFragment_shouldNotUseFeatureFactory() {
|
||||
when(mUserManager.isGuestUser()).thenReturn(false);
|
||||
|
||||
mActivity.handleIntent(createQrCodeGeneratorIntent());
|
||||
|
||||
verify(mWifiFeatureProviderMock, never())
|
||||
.getWifiDppQrCodeGeneratorFragment();
|
||||
}
|
||||
|
||||
private static Intent createQrCodeGeneratorIntent() {
|
||||
Intent intent = new Intent(
|
||||
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
|
||||
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
|
||||
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WPA");
|
||||
intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "\\012345678,");
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
@@ -109,21 +109,21 @@ public class WifiHotspotRepositoryTest {
|
||||
doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
|
||||
doReturn(true).when(mWifiManager).is5GHzBandSupported();
|
||||
doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
|
||||
.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
|
||||
.getAllowedChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
|
||||
doReturn(true).when(mWifiManager).is6GHzBandSupported();
|
||||
doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager)
|
||||
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
.getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
|
||||
mRepository = new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager);
|
||||
mRepository.mSecurityType = mSecurityType;
|
||||
mRepository.mSpeedType = mSpeedType;
|
||||
mRepository.mIsDualBand = true;
|
||||
mRepository.mBand5g.isUsableChannelsReady = true;
|
||||
mRepository.mBand5g.isUsableChannelsUnsupported = false;
|
||||
mRepository.mBand5g.hasUsableChannels = true;
|
||||
mRepository.mBand6g.isUsableChannelsReady = true;
|
||||
mRepository.mBand6g.isUsableChannelsUnsupported = false;
|
||||
mRepository.mBand6g.hasUsableChannels = true;
|
||||
mRepository.mBand5g.isChannelsReady = true;
|
||||
mRepository.mBand5g.isChannelsUnsupported = false;
|
||||
mRepository.mBand5g.hasChannels = true;
|
||||
mRepository.mBand6g.isChannelsReady = true;
|
||||
mRepository.mBand6g.isChannelsUnsupported = false;
|
||||
mRepository.mBand6g.hasChannels = true;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -382,7 +382,7 @@ public class WifiHotspotRepositoryTest {
|
||||
@Test
|
||||
public void updateSpeedType_singleBand5gPreferredBut5gUnavailable_get2gSpeedType() {
|
||||
mRepository.mIsDualBand = false;
|
||||
mRepository.mBand5g.hasUsableChannels = false;
|
||||
mRepository.mBand5g.hasChannels = false;
|
||||
SoftApConfiguration config = new SoftApConfiguration.Builder()
|
||||
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
|
||||
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
|
||||
@@ -407,7 +407,7 @@ public class WifiHotspotRepositoryTest {
|
||||
@Test
|
||||
public void updateSpeedType_singleBand6gPreferredBut6gUnavailable_get5gSpeedType() {
|
||||
mRepository.mIsDualBand = false;
|
||||
mRepository.mBand6g.hasUsableChannels = false;
|
||||
mRepository.mBand6g.hasChannels = false;
|
||||
SoftApConfiguration config = new SoftApConfiguration.Builder()
|
||||
.setBand(WIFI_6GHZ_BAND_PREFERRED).build();
|
||||
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
|
||||
@@ -420,8 +420,8 @@ public class WifiHotspotRepositoryTest {
|
||||
@Test
|
||||
public void updateSpeedType_singleBand6gPreferredBut5gAnd6gUnavailable_get2gSpeedType() {
|
||||
mRepository.mIsDualBand = false;
|
||||
mRepository.mBand5g.hasUsableChannels = false;
|
||||
mRepository.mBand6g.hasUsableChannels = false;
|
||||
mRepository.mBand5g.hasChannels = false;
|
||||
mRepository.mBand6g.hasChannels = false;
|
||||
SoftApConfiguration config = new SoftApConfiguration.Builder()
|
||||
.setBand(WIFI_6GHZ_BAND_PREFERRED).build();
|
||||
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
|
||||
@@ -446,7 +446,7 @@ public class WifiHotspotRepositoryTest {
|
||||
@Test
|
||||
public void updateSpeedType_dualBand2gAnd5gBut5gUnavailable_get2gSpeedType() {
|
||||
mRepository.mIsDualBand = true;
|
||||
mRepository.mBand5g.hasUsableChannels = false;
|
||||
mRepository.mBand5g.hasChannels = false;
|
||||
SoftApConfiguration config = new SoftApConfiguration.Builder()
|
||||
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
|
||||
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
|
||||
@@ -562,20 +562,20 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void is5gAvailable_hasUsableChannels_returnTrue() {
|
||||
public void is5gAvailable_hasChannels_returnTrue() {
|
||||
mRepository.mIs5gBandSupported = true;
|
||||
// Reset m5gBand to trigger an update
|
||||
mRepository.mBand5g.isUsableChannelsReady = false;
|
||||
mRepository.mBand5g.isChannelsReady = false;
|
||||
|
||||
assertThat(mRepository.is5gAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void is5gAvailable_noUsableChannels_returnFalse() {
|
||||
public void is5gAvailable_noChannels_returnFalse() {
|
||||
mRepository.mIs5gBandSupported = true;
|
||||
// Reset m5gBand to trigger an update
|
||||
mRepository.mBand5g.isUsableChannelsReady = false;
|
||||
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
|
||||
mRepository.mBand5g.isChannelsReady = false;
|
||||
when(mWifiManager.getAllowedChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
|
||||
.thenReturn(null);
|
||||
|
||||
assertThat(mRepository.is5gAvailable()).isFalse();
|
||||
@@ -585,7 +585,7 @@ public class WifiHotspotRepositoryTest {
|
||||
@UiThreadTest
|
||||
public void get5gAvailable_shouldNotReturnNull() {
|
||||
// Reset m5gBand to trigger an update
|
||||
mRepository.mBand5g.isUsableChannelsReady = false;
|
||||
mRepository.mBand5g.isChannelsReady = false;
|
||||
|
||||
assertThat(mRepository.get5gAvailable()).isNotNull();
|
||||
}
|
||||
@@ -606,20 +606,20 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void is6gAvailable_hasUsableChannels_returnTrue() {
|
||||
public void is6gAvailable_hasChannels_returnTrue() {
|
||||
mRepository.mIs6gBandSupported = true;
|
||||
// Reset m6gBand to trigger an update
|
||||
mRepository.mBand6g.isUsableChannelsReady = false;
|
||||
mRepository.mBand6g.isChannelsReady = false;
|
||||
|
||||
assertThat(mRepository.is6gAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void is6gAvailable_noUsableChannels_returnFalse() {
|
||||
public void is6gAvailable_noChannels_returnFalse() {
|
||||
mRepository.mIs6gBandSupported = true;
|
||||
// Reset m6gBand to trigger an update
|
||||
mRepository.mBand6g.isUsableChannelsReady = false;
|
||||
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
|
||||
mRepository.mBand6g.isChannelsReady = false;
|
||||
when(mWifiManager.getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
|
||||
.thenReturn(null);
|
||||
|
||||
assertThat(mRepository.is6gAvailable()).isFalse();
|
||||
@@ -658,33 +658,33 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChannelAvailable_throwIllegalArgumentException_hasUsableChannelsFalse() {
|
||||
public void isChannelAvailable_throwIllegalArgumentException_hasChannelsFalse() {
|
||||
doThrow(IllegalArgumentException.class).when(mWifiManager)
|
||||
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
.getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
|
||||
mRepository.isChannelAvailable(mRepository.mBand6g);
|
||||
|
||||
assertThat(mRepository.mBand6g.hasUsableChannels).isFalse();
|
||||
assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isTrue();
|
||||
assertThat(mRepository.mBand6g.hasChannels).isFalse();
|
||||
assertThat(mRepository.mBand6g.isChannelsUnsupported).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChannelAvailable_throwUnsupportedOperationException_hasUsableChannelsFalse() {
|
||||
public void isChannelAvailable_throwUnsupportedOperationException_hasChannelsFalse() {
|
||||
doThrow(UnsupportedOperationException.class).when(mWifiManager)
|
||||
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
.getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
|
||||
|
||||
mRepository.isChannelAvailable(mRepository.mBand6g);
|
||||
|
||||
assertThat(mRepository.mBand6g.hasUsableChannels).isFalse();
|
||||
assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isTrue();
|
||||
assertThat(mRepository.mBand6g.hasChannels).isFalse();
|
||||
assertThat(mRepository.mBand6g.isChannelsUnsupported).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChannelAvailable_noExceptionAndHasUsableChannels_hasUsableChannelsTrue() {
|
||||
public void isChannelAvailable_noExceptionAndHasChannels_hasChannelsTrue() {
|
||||
mRepository.isChannelAvailable(mRepository.mBand6g);
|
||||
|
||||
assertThat(mRepository.mBand6g.hasUsableChannels).isTrue();
|
||||
assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isFalse();
|
||||
assertThat(mRepository.mBand6g.hasChannels).isTrue();
|
||||
assertThat(mRepository.mBand6g.isChannelsUnsupported).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -744,9 +744,9 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateCapabilityChanged_band5gUsableChannelsUnsupported_update5gAvailable() {
|
||||
public void updateCapabilityChanged_band5gChannelsUnsupported_update5gAvailable() {
|
||||
mRepository = spy(new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager));
|
||||
mRepository.mBand5g.isUsableChannelsUnsupported = true;
|
||||
mRepository.mBand5g.isChannelsUnsupported = true;
|
||||
|
||||
mRepository.updateCapabilityChanged();
|
||||
|
||||
@@ -755,9 +755,9 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateCapabilityChanged_band6gUsableChannelsUnsupported_update5gAvailable() {
|
||||
public void updateCapabilityChanged_band6gChannelsUnsupported_update5gAvailable() {
|
||||
mRepository = spy(new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager));
|
||||
mRepository.mBand6g.isUsableChannelsUnsupported = true;
|
||||
mRepository.mBand6g.isChannelsUnsupported = true;
|
||||
|
||||
mRepository.updateCapabilityChanged();
|
||||
|
||||
@@ -766,18 +766,18 @@ public class WifiHotspotRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_isUsableChannelsUnsupportedFalse_returnHasUsableChannels() {
|
||||
mRepository.mBand6g.isUsableChannelsUnsupported = false;
|
||||
mRepository.mBand6g.hasUsableChannels = false;
|
||||
public void isAvailable_isChannelsUnsupportedFalse_returnHasChannels() {
|
||||
mRepository.mBand6g.isChannelsUnsupported = false;
|
||||
mRepository.mBand6g.hasChannels = false;
|
||||
mRepository.mBand6g.hasCapability = true;
|
||||
|
||||
assertThat(mRepository.mBand6g.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_isUsableChannelsUnsupportedTrue_returnHasCapability() {
|
||||
mRepository.mBand6g.isUsableChannelsUnsupported = true;
|
||||
mRepository.mBand6g.hasUsableChannels = false;
|
||||
public void isAvailable_isChannelsUnsupportedTrue_returnHasCapability() {
|
||||
mRepository.mBand6g.isChannelsUnsupported = true;
|
||||
mRepository.mBand6g.hasChannels = false;
|
||||
mRepository.mBand6g.hasCapability = true;
|
||||
|
||||
assertThat(mRepository.mBand6g.isAvailable()).isTrue();
|
||||
|
Reference in New Issue
Block a user