passwordRequirements = new ArrayList<>();
- if (mPasswordMinUpperCase > 0) {
- passwordRequirements.add(MIN_UPPER_LETTERS_IN_PASSWORD);
- }
- if (mPasswordMinLowerCase > 0) {
- passwordRequirements.add(MIN_LOWER_LETTERS_IN_PASSWORD);
- }
- if (mPasswordMinLetters > 0) {
- if (mPasswordMinLetters > mPasswordMinUpperCase + mPasswordMinLowerCase) {
- passwordRequirements.add(MIN_LETTER_IN_PASSWORD);
- }
- }
- if (mPasswordMinNumeric > 0) {
- passwordRequirements.add(MIN_NUMBER_IN_PASSWORD);
- }
- if (mPasswordMinSymbols > 0) {
- passwordRequirements.add(MIN_SYMBOLS_IN_PASSWORD);
- }
- if (mPasswordMinNonLetter > 0) {
- if (mPasswordMinNonLetter > mPasswordMinNumeric + mPasswordMinSymbols) {
- passwordRequirements.add(MIN_NON_LETTER_IN_PASSWORD);
- }
- }
- // Convert list to array.
- mPasswordRequirements = passwordRequirements.stream().mapToInt(i -> i).toArray();
mPasswordRestrictionView = view.findViewById(R.id.password_requirements_view);
mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity()));
mPasswordRequirementAdapter = new PasswordRequirementAdapter();
@@ -603,13 +592,12 @@ public class ChooseLockPassword extends SettingsActivity {
/**
* Read the requirements from {@link DevicePolicyManager} and intent and aggregate them.
- *
- * @param intent the incoming intent
*/
- private void processPasswordRequirements(Intent intent) {
+ private void loadDpmPasswordRequirements() {
final int dpmPasswordQuality = mLockPatternUtils.getRequestedPasswordQuality(mUserId);
- mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
- mRequestedQuality), dpmPasswordQuality);
+ if (dpmPasswordQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX) {
+ mPasswordNumSequenceAllowed = false;
+ }
mPasswordMinLength = Math.max(LockPatternUtils.MIN_LOCK_PASSWORD_SIZE,
mLockPatternUtils.getRequestedMinimumPasswordLength(mUserId));
mPasswordMaxLength = mLockPatternUtils.getMaximumPasswordLength(mRequestedQuality);
@@ -620,7 +608,7 @@ public class ChooseLockPassword extends SettingsActivity {
mPasswordMinSymbols = mLockPatternUtils.getRequestedPasswordMinimumSymbols(mUserId);
mPasswordMinNonLetter = mLockPatternUtils.getRequestedPasswordMinimumNonLetter(mUserId);
- // Modify the value based on dpm policy.
+ // Modify the value based on dpm policy
switch (dpmPasswordQuality) {
case PASSWORD_QUALITY_ALPHABETIC:
if (mPasswordMinLetters == 0) {
@@ -646,19 +634,88 @@ public class ChooseLockPassword extends SettingsActivity {
mPasswordMinSymbols = 0;
mPasswordMinNonLetter = 0;
}
+
mPasswordMinLengthToFulfillAllPolicies = getMinLengthToFulfillAllPolicies();
}
+ /**
+ * Merges the dpm requirements and the min complexity requirements.
+ *
+ * Since there are more than one set of metrics to meet the min complexity requirement,
+ * and we are not hard-coding any one of them to be the requirements the user must fulfil,
+ * we are taking what the user has already entered into account when compiling the list of
+ * requirements from min complexity. Then we merge this list with the DPM requirements, and
+ * present the merged set as validation results to the user on the UI.
+ *
+ *
For example, suppose min complexity requires either ALPHABETIC(8+), or
+ * ALPHANUMERIC(6+). If the user has entered "a", the length requirement displayed on the UI
+ * would be 8. Then the user appends "1" to make it "a1". We now know the user is entering
+ * an alphanumeric password so we would update the min complexity required min length to 6.
+ * This might result in a little confusion for the user but the UI does not support showing
+ * multiple sets of requirements / validation results as options to users, this is the best
+ * we can do now.
+ */
+ private void mergeMinComplexityAndDpmRequirements(int userEnteredPasswordQuality) {
+ if (mRequestedMinComplexity == PASSWORD_COMPLEXITY_NONE) {
+ // dpm requirements are dominant if min complexity is none
+ return;
+ }
+
+ // reset dpm requirements
+ loadDpmPasswordRequirements();
+
+ PasswordMetrics minMetrics = PasswordMetrics.getMinimumMetrics(
+ mRequestedMinComplexity, userEnteredPasswordQuality, mRequestedQuality,
+ requiresNumeric(), requiresLettersOrSymbols());
+ mPasswordNumSequenceAllowed = mPasswordNumSequenceAllowed
+ && minMetrics.quality != PASSWORD_QUALITY_NUMERIC_COMPLEX;
+ mPasswordMinLength = Math.max(mPasswordMinLength, minMetrics.length);
+ mPasswordMinLetters = Math.max(mPasswordMinLetters, minMetrics.letters);
+ mPasswordMinUpperCase = Math.max(mPasswordMinUpperCase, minMetrics.upperCase);
+ mPasswordMinLowerCase = Math.max(mPasswordMinLowerCase, minMetrics.lowerCase);
+ mPasswordMinNumeric = Math.max(mPasswordMinNumeric, minMetrics.numeric);
+ mPasswordMinSymbols = Math.max(mPasswordMinSymbols, minMetrics.symbols);
+ mPasswordMinNonLetter = Math.max(mPasswordMinNonLetter, minMetrics.nonLetter);
+
+ if (minMetrics.quality == PASSWORD_QUALITY_ALPHABETIC) {
+ if (!requiresLettersOrSymbols()) {
+ mPasswordMinLetters = 1;
+ }
+ }
+ if (minMetrics.quality == PASSWORD_QUALITY_ALPHANUMERIC) {
+ if (!requiresLettersOrSymbols()) {
+ mPasswordMinLetters = 1;
+ }
+ if (!requiresNumeric()) {
+ mPasswordMinNumeric = 1;
+ }
+ }
+
+ mPasswordMinLengthToFulfillAllPolicies = getMinLengthToFulfillAllPolicies();
+ }
+
+ private boolean requiresLettersOrSymbols() {
+ // This is the condition for the password to be considered ALPHABETIC according to
+ // PasswordMetrics.computeForPassword()
+ return mPasswordMinLetters + mPasswordMinUpperCase
+ + mPasswordMinLowerCase + mPasswordMinSymbols + mPasswordMinNonLetter > 0;
+ }
+
+ private boolean requiresNumeric() {
+ return mPasswordMinNumeric > 0;
+ }
+
/**
* Validates PIN/Password and returns the validation result.
*
* @param password the raw password the user typed in
* @return the validation result.
*/
- private int validatePassword(String password) {
+ @VisibleForTesting
+ int validatePassword(String password) {
int errorCode = NO_ERROR;
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
-
+ mergeMinComplexityAndDpmRequirements(metrics.quality);
if (password.length() < mPasswordMinLength) {
if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) {
@@ -668,14 +725,25 @@ public class ChooseLockPassword extends SettingsActivity {
errorCode |= TOO_LONG;
} else {
// The length requirements are fulfilled.
- final int dpmQuality = mLockPatternUtils.getRequestedPasswordQuality(mUserId);
- if (dpmQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX &&
- metrics.numeric == password.length()) {
+ if (!mPasswordNumSequenceAllowed
+ && !requiresLettersOrSymbols()
+ && metrics.numeric == password.length()) {
// Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
- // if DevicePolicyManager requires a complex numeric password. There can be
- // two cases in the UI: 1. User chooses to enroll a PIN, 2. User chooses to
- // enroll a password but enters a numeric-only pin. We should carry out the
- // sequence check in both cases.
+ // if DevicePolicyManager or min password complexity requires a complex numeric
+ // password. There can be two cases in the UI: 1. User chooses to enroll a
+ // PIN, 2. User chooses to enroll a password but enters a numeric-only pin. We
+ // should carry out the sequence check in both cases.
+ //
+ // Conditions for the !requiresLettersOrSymbols() to be necessary:
+ // - DPM requires NUMERIC_COMPLEX
+ // - min complexity not NONE, user picks PASSWORD type so ALPHABETIC or
+ // ALPHANUMERIC is required
+ // Imagine user has entered "12345678", if we don't skip the sequence check, the
+ // validation result would show both "requires a letter" and "sequence not
+ // allowed", while the only requirement the user needs to know is "requires a
+ // letter" because once the user has fulfilled the alphabetic requirement, the
+ // password would not be containing only digits so this check would not be
+ // performed anyway.
final int sequence = PasswordMetrics.maxLengthSequence(password);
if (sequence > PasswordMetrics.MAX_ALLOWED_SEQUENCE) {
errorCode |= CONTAIN_SEQUENTIAL_DIGITS;
@@ -706,43 +774,24 @@ public class ChooseLockPassword extends SettingsActivity {
}
}
- // Check the requirements one by one.
- for (int i = 0; i < mPasswordRequirements.length; i++) {
- int passwordRestriction = mPasswordRequirements[i];
- switch (passwordRestriction) {
- case MIN_LETTER_IN_PASSWORD:
- if (metrics.letters < mPasswordMinLetters) {
- errorCode |= NOT_ENOUGH_LETTER;
- }
- break;
- case MIN_UPPER_LETTERS_IN_PASSWORD:
- if (metrics.upperCase < mPasswordMinUpperCase) {
- errorCode |= NOT_ENOUGH_UPPER_CASE;
- }
- break;
- case MIN_LOWER_LETTERS_IN_PASSWORD:
- if (metrics.lowerCase < mPasswordMinLowerCase) {
- errorCode |= NOT_ENOUGH_LOWER_CASE;
- }
- break;
- case MIN_SYMBOLS_IN_PASSWORD:
- if (metrics.symbols < mPasswordMinSymbols) {
- errorCode |= NOT_ENOUGH_SYMBOLS;
- }
- break;
- case MIN_NUMBER_IN_PASSWORD:
- if (metrics.numeric < mPasswordMinNumeric) {
- errorCode |= NOT_ENOUGH_DIGITS;
- }
- break;
- case MIN_NON_LETTER_IN_PASSWORD:
- if (metrics.nonLetter < mPasswordMinNonLetter) {
- errorCode |= NOT_ENOUGH_NON_LETTER;
- }
- break;
- }
+ if (metrics.letters < mPasswordMinLetters) {
+ errorCode |= NOT_ENOUGH_LETTER;
+ }
+ if (metrics.upperCase < mPasswordMinUpperCase) {
+ errorCode |= NOT_ENOUGH_UPPER_CASE;
+ }
+ if (metrics.lowerCase < mPasswordMinLowerCase) {
+ errorCode |= NOT_ENOUGH_LOWER_CASE;
+ }
+ if (metrics.symbols < mPasswordMinSymbols) {
+ errorCode |= NOT_ENOUGH_SYMBOLS;
+ }
+ if (metrics.numeric < mPasswordMinNumeric) {
+ errorCode |= NOT_ENOUGH_DIGITS;
+ }
+ if (metrics.nonLetter < mPasswordMinNonLetter) {
+ errorCode |= NOT_ENOUGH_NON_LETTER;
}
-
return errorCode;
}
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 1f0bb4eb836..584cc6162e3 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -50,8 +50,8 @@ import com.android.settings.core.InstrumentedFragment;
import com.android.settings.notification.RedactionInterstitial;
import com.google.android.collect.Lists;
-import com.google.android.setupcompat.item.FooterButton;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import java.util.ArrayList;
@@ -489,7 +489,7 @@ public class ChooseLockPattern extends SettingsActivity {
}
}
- final ButtonFooterMixin mixin = layout.getMixin(ButtonFooterMixin.class);
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
mixin.setSecondaryButton(
new FooterButton.Builder(getActivity())
.setText(R.string.lockpattern_tutorial_cancel_label)
@@ -512,7 +512,6 @@ public class ChooseLockPattern extends SettingsActivity {
return layout;
}
-
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 8d0fa602d66..32e8eafa2f6 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -45,6 +45,18 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_FOR_FACE = "for_face";
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
+ /**
+ * Intent extra for passing the requested min password complexity to later steps in the set new
+ * screen lock flow.
+ */
+ public static final String EXTRA_KEY_REQUESTED_MIN_COMPLEXITY = "requested_min_complexity";
+
+ /**
+ * Intent extra for passing the label of the calling app to later steps in the set new screen
+ * lock flow.
+ */
+ public static final String EXTRA_KEY_CALLER_APP_NAME = "caller_app_name";
+
/**
* When invoked via {@link ConfirmLockPassword.InternalActivity}, this flag
* controls if we relax the enforcement of
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 5eb1f322c27..3fa2f6ac08b 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -23,6 +23,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.Intent;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
@@ -87,6 +88,8 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private TrustManager mTrustManager;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private Handler mHandler = new Handler(Looper.getMainLooper());
+ private boolean mIsFallback; // BiometricPrompt fallback
+ private boolean mCCLaunched;
private String mTitle;
private String mDetails;
@@ -102,6 +105,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (!mGoingToBackground) {
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) {
+ if (mIsFallback) {
+ mBiometricManager.onConfirmDeviceCredentialError(
+ BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+ getString(
+ com.android.internal.R.string
+ .biometric_error_user_canceled));
+ }
finish();
} else {
// All other errors go to some version of CC
@@ -118,6 +128,10 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
ConfirmDeviceCredentialUtils.checkForPendingIntent(
ConfirmDeviceCredentialActivity.this);
+ if (mIsFallback) {
+ mBiometricManager.onConfirmDeviceCredentialSuccess();
+ }
+
setResult(Activity.RESULT_OK);
finish();
}
@@ -158,6 +172,19 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+ Bundle bpBundle =
+ intent.getBundleExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE);
+ if (bpBundle != null) {
+ mIsFallback = true;
+ // TODO: CDC maybe should show description as well.
+ mTitle = bpBundle.getString(BiometricPrompt.KEY_TITLE);
+ mDetails = bpBundle.getString(BiometricPrompt.KEY_SUBTITLE);
+ } else {
+ bpBundle = new Bundle();
+ bpBundle.putString(BiometricPrompt.KEY_TITLE, mTitle);
+ bpBundle.putString(BiometricPrompt.KEY_SUBTITLE, mDetails);
+ }
+
boolean launchedBiometric = false;
boolean launchedCDC = false;
// If the target is a managed user and user key not unlocked yet, we will force unlock
@@ -170,7 +197,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
&& !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
mCredentialMode = CREDENTIAL_MANAGED;
if (isBiometricAllowed(effectiveUserId)) {
- showBiometricPrompt();
+ showBiometricPrompt(bpBundle);
launchedBiometric = true;
} else {
showConfirmCredentials();
@@ -181,7 +208,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
if (isBiometricAllowed(effectiveUserId)) {
// Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
// onAuthenticationError and do the right thing automatically.
- showBiometricPrompt();
+ showBiometricPrompt(bpBundle);
launchedBiometric = true;
} else {
showConfirmCredentials();
@@ -216,6 +243,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
if (mBiometricFragment != null) {
mBiometricFragment.cancel();
}
+
+ if (mIsFallback && !mCCLaunched) {
+ mBiometricManager.onConfirmDeviceCredentialError(
+ BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+ getString(com.android.internal.R.string.biometric_error_user_canceled));
+ }
+
finish();
} else {
mGoingToBackground = false;
@@ -242,7 +276,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
&& !isBiometricDisabledByAdmin(effectiveUserId);
}
- private void showBiometricPrompt() {
+ private void showBiometricPrompt(Bundle bundle) {
mBiometricManager.setActiveUser(mUserId);
mBiometricFragment = (BiometricFragment) getSupportFragmentManager()
@@ -250,13 +284,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
boolean newFragment = false;
if (mBiometricFragment == null) {
- final BiometricFragment.PromptInfo info = new BiometricFragment.PromptInfo.Builder()
- .setTitle(mTitle)
- .setSubtitle(mDetails)
- .setNegativeButtonText(getResources()
- .getString(R.string.confirm_device_credential_use_alternate_method))
- .build();
- mBiometricFragment = BiometricFragment.newInstance(info);
+ mBiometricFragment = BiometricFragment.newInstance(bundle);
newFragment = true;
}
mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
@@ -272,6 +300,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
* Shows ConfirmDeviceCredentials for normal apps.
*/
private void showConfirmCredentials() {
+ mCCLaunched = true;
boolean launched = false;
if (mCredentialMode == CREDENTIAL_MANAGED) {
// We set the challenge as 0L, so it will force to unlock managed profile when it
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
index c00f9ab124c..56e6573d768 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
@@ -17,6 +17,8 @@
package com.android.settings.password;
import android.app.KeyguardManager;
+import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricManager;
import android.os.Bundle;
import android.os.UserManager;
import android.view.MenuItem;
@@ -45,6 +47,7 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
private boolean mFirstTimeVisible = true;
private boolean mIsKeyguardLocked = false;
private ConfirmCredentialTheme mConfirmCredentialTheme;
+ private BiometricManager mBiometricManager;
private boolean isInternalActivity() {
return (this instanceof ConfirmLockPassword.InternalActivity)
@@ -68,6 +71,8 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
}
super.onCreate(savedState);
+ mBiometricManager = getSystemService(BiometricManager.class);
+
if (mConfirmCredentialTheme == ConfirmCredentialTheme.NORMAL) {
// Prevent the content parent from consuming the window insets because GlifLayout uses
// it to show the status bar background.
@@ -140,6 +145,17 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
}
}
+ @Override
+ public void onStop() {
+ super.onStop();
+ // TODO(b/123378871): Remove when moved.
+ if (!isChangingConfigurations()) {
+ mBiometricManager.onConfirmDeviceCredentialError(
+ BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+ getString(com.android.internal.R.string.biometric_error_user_canceled));
+ }
+ }
+
@Override
public void finish() {
super.finish();
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
index 2de7625b9ed..e14ec811353 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
@@ -29,6 +29,7 @@ import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserManager;
@@ -84,6 +85,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
protected final Handler mHandler = new Handler();
protected boolean mFrp;
private CharSequence mFrpAlternateButtonText;
+ protected BiometricManager mBiometricManager;
private boolean isInternalActivity() {
return (getActivity() instanceof ConfirmLockPassword.InternalActivity)
@@ -107,6 +109,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
mLockPatternUtils = new LockPatternUtils(getActivity());
mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService(
Context.DEVICE_POLICY_SERVICE);
+ mBiometricManager = getActivity().getSystemService(BiometricManager.class);
}
@Override
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 7344077d742..f8938703bd7 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -437,6 +437,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
mUserManager, mEffectiveUserId);
}
+ mBiometricManager.onConfirmDeviceCredentialSuccess();
startDisappearAnimation(intent);
ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
} else {
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 5645193c01a..29cdfef0516 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -490,6 +490,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
mUserManager, mEffectiveUserId);
}
+ mBiometricManager.onConfirmDeviceCredentialSuccess();
startDisappearAnimation(intent);
ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
} else {
diff --git a/src/com/android/settings/password/PasswordUtils.java b/src/com/android/settings/password/PasswordUtils.java
new file mode 100644
index 00000000000..5f118cf0e6c
--- /dev/null
+++ b/src/com/android/settings/password/PasswordUtils.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.password;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.settings.Utils;
+
+public final class PasswordUtils extends com.android.settingslib.Utils {
+
+ private static final String TAG = "Settings";
+
+ private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+
+ /**
+ * Returns whether the uid which the activity with {@code activityToken} is launched from has
+ * been granted the {@code permission}.
+ */
+ public static boolean isCallingAppPermitted(Context context, IBinder activityToken,
+ String permission) {
+ try {
+ return context.checkPermission(permission, /* pid= */ -1,
+ ActivityManager.getService().getLaunchedFromUid(activityToken))
+ == PackageManager.PERMISSION_GRANTED;
+ } catch (RemoteException e) {
+ Log.v(TAG, "Could not talk to activity manager.", e);
+ return false;
+ }
+ }
+
+ /**
+ * Returns the label of the package which the activity with {@code activityToken} is launched
+ * from or {@code null} if it is launched from the settings app itself.
+ */
+ @Nullable
+ public static CharSequence getCallingAppLabel(Context context, IBinder activityToken) {
+ String pkg = getCallingAppPackageName(activityToken);
+ if (pkg == null || pkg.equals(SETTINGS_PACKAGE_NAME)) {
+ return null;
+ }
+
+ return Utils.getApplicationLabel(context, pkg);
+ }
+
+ /**
+ * Returns the package name which the activity with {@code activityToken} is launched from.
+ */
+ @Nullable
+ private static String getCallingAppPackageName(IBinder activityToken) {
+ String pkg = null;
+ try {
+ pkg = ActivityManager.getService().getLaunchedFromPackage(activityToken);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Could not talk to activity manager.", e);
+ }
+ return pkg;
+ }
+
+ /** Crashes the calling application and provides it with {@code message}. */
+ public static void crashCallingApplication(IBinder activityToken, String message) {
+ IActivityManager am = ActivityManager.getService();
+ try {
+ int uid = am.getLaunchedFromUid(activityToken);
+ int userId = UserHandle.getUserId(uid);
+ am.crashApplication(
+ uid,
+ /* initialPid= */ -1,
+ getCallingAppPackageName(activityToken),
+ userId,
+ message);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Could not talk to activity manager.", e);
+ }
+ }
+}
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index 99f67cb13d5..8ea85144ea7 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -16,13 +16,22 @@
package com.android.settings.password;
+import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManager.PasswordComplexity;
+import android.app.admin.PasswordMetrics;
import android.content.Intent;
import android.os.Bundle;
+import android.os.IBinder;
import android.util.Log;
import com.android.settings.Utils;
@@ -37,6 +46,21 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo
private String mNewPasswordAction;
private SetNewPasswordController mSetNewPasswordController;
+ /**
+ * From intent extra {@link DevicePolicyManager#EXTRA_PASSWORD_COMPLEXITY}.
+ *
+ *
This is used only if caller has the required permission and activity is launched by
+ * {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD}.
+ */
+ private @PasswordComplexity int mRequestedMinComplexity = PASSWORD_COMPLEXITY_NONE;
+
+ /**
+ * Label of the app which launches this activity.
+ *
+ *
Value would be {@code null} if launched from settings app.
+ */
+ private String mCallerAppName = null;
+
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
@@ -48,6 +72,25 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo
finish();
return;
}
+
+ IBinder activityToken = getActivityToken();
+ mCallerAppName = (String) PasswordUtils.getCallingAppLabel(this, activityToken);
+ if (ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
+ && getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY)) {
+ boolean hasPermission = PasswordUtils.isCallingAppPermitted(
+ this, activityToken, GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ if (hasPermission) {
+ mRequestedMinComplexity = PasswordMetrics.sanitizeComplexityLevel(getIntent()
+ .getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE));
+ } else {
+ PasswordUtils.crashCallingApplication(activityToken,
+ "Must have permission " + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY
+ + " to use extra " + EXTRA_PASSWORD_COMPLEXITY);
+ finish();
+ return;
+ }
+ }
+
mSetNewPasswordController = SetNewPasswordController.create(
this, this, getIntent(), getActivityToken());
mSetNewPasswordController.dispatchSetNewPasswordIntent();
@@ -60,6 +103,12 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo
: new Intent(this, ChooseLockGeneric.class);
intent.setAction(mNewPasswordAction);
intent.putExtras(chooseLockFingerprintExtras);
+ if (mCallerAppName != null) {
+ intent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName);
+ }
+ if (mRequestedMinComplexity != PASSWORD_COMPLEXITY_NONE) {
+ intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, mRequestedMinComplexity);
+ }
startActivity(intent);
finish();
}
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index a0f8bae0502..33c3edb9d38 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -16,11 +16,17 @@
package com.android.settings.password;
+import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
+
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.UserHandle;
import android.view.LayoutInflater;
import android.view.View;
@@ -48,6 +54,7 @@ import com.google.android.setupdesign.GlifPreferenceLayout;
* Other changes should be done to ChooseLockGeneric class instead and let this class inherit
* those changes.
*/
+// TODO(b/123225425): Restrict SetupChooseLockGeneric to be accessible by SUW only
public class SetupChooseLockGeneric extends ChooseLockGeneric {
private static final String KEY_UNLOCK_SET_DO_LATER = "unlock_set_do_later";
@@ -71,6 +78,20 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
+
+ if(getIntent().hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)) {
+ IBinder activityToken = getActivityToken();
+ boolean hasPermission = PasswordUtils.isCallingAppPermitted(
+ this, activityToken, GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ if (!hasPermission) {
+ PasswordUtils.crashCallingApplication(activityToken,
+ "Must have permission " + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY
+ + " to use extra " + EXTRA_PASSWORD_COMPLEXITY);
+ finish();
+ return;
+ }
+ }
+
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
layout.setFitsSystemWindows(false);
}
diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
index 3fac672b608..e43140f0ef8 100644
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
@@ -76,6 +76,7 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
.setEmptyText(R.string.permission_bar_chart_empty_text)
.setDetailsOnClickListener((View v) -> {
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
+ intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
mContext.startActivity(intent);
})
.build();
@@ -102,7 +103,7 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
private void retrievePermissionUsageData() {
mContext.getSystemService(PermissionControllerManager.class).getPermissionUsages(
- false /* countSystem */, (int) DAYS.toSeconds(1),
+ false /* countSystem */, (int) DAYS.toMillis(1),
mContext.getMainExecutor() /* executor */, this /* callback */);
}
@@ -111,6 +112,9 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
return null;
}
+ // STOPSHIP: Ignore the STORAGE group since it's going away.
+ usageInfos.removeIf(usage -> usage.getName().equals("android.permission-group.STORAGE"));
+
final BarViewInfo[] barViewInfos = new BarViewInfo[
Math.min(BarChartPreference.MAXIMUM_BAR_VIEWS, usageInfos.size())];
diff --git a/src/com/android/settings/security/ConfigureKeyGuardDialog.java b/src/com/android/settings/security/ConfigureKeyGuardDialog.java
deleted file mode 100644
index fff106c2791..00000000000
--- a/src/com/android/settings/security/ConfigureKeyGuardDialog.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2017 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.security;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.admin.DevicePolicyManager;
-import android.app.settings.SettingsEnums;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-
-import com.android.settings.CredentialStorage;
-import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.password.ChooseLockGeneric;
-
-/**
- * Prompt for key guard configuration confirmation.
- */
-public class ConfigureKeyGuardDialog extends InstrumentedDialogFragment
- implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
-
- public static final String TAG = "ConfigureKeyGuardDialog";
-
- private boolean mConfigureConfirmed;
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.CONFIGURE_KEYGUARD_DIALOG;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity())
- .setTitle(android.R.string.dialog_alert_title)
- .setMessage(R.string.credentials_configure_lock_screen_hint)
- .setPositiveButton(R.string.credentials_configure_lock_screen_button, this)
- .setNegativeButton(android.R.string.cancel, this)
- .create();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int button) {
- mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- if (mConfigureConfirmed) {
- mConfigureConfirmed = false;
- startPasswordSetup();
- return;
- } else {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.finish();
- }
- }
- }
-
- @VisibleForTesting
- void startPasswordSetup() {
- Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
- intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
- CredentialStorage.MIN_PASSWORD_QUALITY);
- startActivity(intent);
- }
-}
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/security/CredentialStorage.java
similarity index 75%
rename from src/com/android/settings/CredentialStorage.java
rename to src/com/android/settings/security/CredentialStorage.java
index 5ab543f65d9..99937eee472 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/security/CredentialStorage.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.security;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
@@ -44,8 +44,8 @@ import androidx.fragment.app.FragmentActivity;
import com.android.internal.widget.LockPatternUtils;
import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import com.android.settings.R;
import com.android.settings.password.ChooseLockSettingsHelper;
-import com.android.settings.security.ConfigureKeyGuardDialog;
import com.android.settings.vpn2.VpnUtils;
import java.io.ByteArrayInputStream;
@@ -55,46 +55,12 @@ import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
/**
- * CredentialStorage handles KeyStore reset, unlock, and install.
- *
- * CredentialStorage has a pretty convoluted state machine to migrate
- * from the old style separate keystore password to a new key guard
- * based password, as well as to deal with setting up the key guard if
- * necessary.
- *
- * KeyStore: UNINITALIZED
- * KeyGuard: OFF
- * Action: set up key guard
- * Notes: factory state
- *
- * KeyStore: UNINITALIZED
- * KeyGuard: ON
- * Action: confirm key guard
- * Notes: user had key guard but no keystore and upgraded from pre-ICS
- * OR user had key guard and pre-ICS keystore password which was then reset
- *
- * KeyStore: LOCKED
- * KeyGuard: OFF/ON
- * Action: confirm key guard
- * Notes: request normal unlock to unlock the keystore.
- * if unlock, ensure key guard before install.
- * if reset, treat as UNINITALIZED/OFF
- *
- * KeyStore: UNLOCKED
- * KeyGuard: OFF
- * Action: set up key guard
- * Notes: ensure key guard, then proceed
- *
- * KeyStore: UNLOCKED
- * keyguard: ON
- * Action: normal unlock/install
- * Notes: this is the common case
+ * CredentialStorage handles resetting and installing keys into KeyStore.
*/
public final class CredentialStorage extends FragmentActivity {
private static final String TAG = "CredentialStorage";
- public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
public static final String ACTION_RESET = "com.android.credentials.RESET";
@@ -102,8 +68,7 @@ public final class CredentialStorage extends FragmentActivity {
// lower than this, keystore should not be activated.
public static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
- private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;
+ private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 1;
private final KeyStore mKeyStore = KeyStore.getInstance();
private LockPatternUtils mUtils;
@@ -133,75 +98,26 @@ public final class CredentialStorage extends FragmentActivity {
if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) {
mInstallBundle = intent.getExtras();
}
- // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL
- handleUnlockOrInstall();
+ handleInstall();
}
} else {
- // Users can set a screen lock if there is none even if they can't modify the
- // credentials store.
- if (ACTION_UNLOCK.equals(action) && mKeyStore.state() == KeyStore.State.UNINITIALIZED) {
- ensureKeyGuard();
- } else {
- finish();
- }
+ finish();
}
}
/**
- * Based on the current state of the KeyStore and key guard, try to
- * make progress on unlocking or installing to the keystore.
+ * Install credentials from mInstallBundle into Keystore.
*/
- private void handleUnlockOrInstall() {
+ private void handleInstall() {
// something already decided we are done, do not proceed
if (isFinishing()) {
return;
}
- switch (mKeyStore.state()) {
- case UNINITIALIZED: {
- ensureKeyGuard();
- return;
- }
- case LOCKED: {
- // Force key guard confirmation
- confirmKeyGuard(CONFIRM_KEY_GUARD_REQUEST);
- return;
- }
- case UNLOCKED: {
- if (!mUtils.isSecure(UserHandle.myUserId())) {
- final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
- dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
- return;
- }
- if (installIfAvailable()) {
- finish();
- }
- return;
- }
+ if (installIfAvailable()) {
+ finish();
}
}
- /**
- * Make sure the user enters the key guard to set or change the
- * keystore password. This can be used in UNINITIALIZED to set the
- * keystore password or UNLOCKED to change the password (as is the
- * case after unlocking with an old-style password).
- */
- private void ensureKeyGuard() {
- if (!mUtils.isSecure(UserHandle.myUserId())) {
- // key guard not setup, doing so will initialize keystore
- final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
- dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
- // will return to onResume after Activity
- return;
- }
- // force key guard confirmation
- if (confirmKeyGuard(CONFIRM_KEY_GUARD_REQUEST)) {
- // will return password value via onActivityResult
- return;
- }
- finish();
- }
-
private boolean isHardwareBackedKey(byte[] keyData) {
try {
final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
@@ -254,15 +170,7 @@ public final class CredentialStorage extends FragmentActivity {
final String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
final byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
- int flags = KeyStore.FLAG_ENCRYPTED;
- if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) {
- // Hardware backed keystore is secure enough to allow for WIFI stack
- // to enable access to secure networks without user intervention
- Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID");
- flags = KeyStore.FLAG_NONE;
- }
-
- if (!mKeyStore.importKey(key, value, uid, flags)) {
+ if (!mKeyStore.importKey(key, value, uid, KeyStore.FLAG_NONE)) {
Log.e(TAG, "Failed to install " + key + " as uid " + uid);
return true;
}
@@ -475,20 +383,7 @@ public final class CredentialStorage extends FragmentActivity {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- // Receive key guard password initiated by confirmKeyGuard.
- if (requestCode == CONFIRM_KEY_GUARD_REQUEST) {
- if (resultCode == Activity.RESULT_OK) {
- final String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
- if (!TextUtils.isEmpty(password)) {
- // success
- mKeyStore.unlock(password);
- // return to onResume
- return;
- }
- }
- // failed confirmation, bail
- finish();
- } else if (requestCode == CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST) {
+ if (requestCode == CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
new ResetKeyStoreAndKeyChain().execute();
return;
diff --git a/src/com/android/settings/security/OWNERS b/src/com/android/settings/security/OWNERS
new file mode 100644
index 00000000000..6e4f5532bd4
--- /dev/null
+++ b/src/com/android/settings/security/OWNERS
@@ -0,0 +1,7 @@
+# Enterprise security reviewers
+eranm@google.com
+pgrafov@google.com
+rubinxu@google.com
+
+# Emergency
+sandness@google.com
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index e842cb97857..3a213df6742 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -154,6 +154,15 @@ public class CustomSliceRegistry {
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath("low_storage")
.build();
+ /**
+ * Backing Uri for NFC Slice
+ */
+ public static final Uri NFC_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("toggle_nfc")
+ .build();
/**
* Backing Uri for Notification channel Slice.
*/
diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java
index 284fd23466d..6df45ba93e3 100644
--- a/src/com/android/settings/slices/SliceBackgroundWorker.java
+++ b/src/com/android/settings/slices/SliceBackgroundWorker.java
@@ -59,10 +59,6 @@ public abstract class SliceBackgroundWorker implements Closeable {
mUri = uri;
}
- protected Uri getUri() {
- return mUri;
- }
-
/**
* Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link Uri}
* if exists
@@ -148,7 +144,14 @@ public abstract class SliceBackgroundWorker implements Closeable {
if (needNotify) {
mCachedResults = results;
- mContext.getContentResolver().notifyChange(mUri, null);
+ notifySliceChange();
}
}
-}
+
+ /**
+ * Notify that data was updated and attempt to sync changes to the Slice.
+ */
+ protected void notifySliceChange() {
+ mContext.getContentResolver().notifyChange(mUri, null);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java
index ec927aec2f5..b72508ed9e4 100644
--- a/src/com/android/settings/vpn2/ConfigDialogFragment.java
+++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java
@@ -56,8 +56,6 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements
ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
private Context mContext;
- private boolean mUnlocking = false;
-
@Override
public int getMetricsCategory() {
@@ -84,27 +82,6 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements
mContext = context;
}
- @Override
- public void onResume() {
- super.onResume();
-
- // Check KeyStore here, so others do not need to deal with it.
- if (!KeyStore.getInstance().isUnlocked()) {
- if (!mUnlocking) {
- // Let us unlock KeyStore. See you later!
- Credentials.getInstance().unlock(mContext);
- } else {
- // We already tried, but it is still not working!
- dismiss();
- }
- mUnlocking = !mUnlocking;
- return;
- }
-
- // Now KeyStore is always unlocked. Reset the flag.
- mUnlocking = false;
- }
-
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
diff --git a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
index 50819e2f6de..14564b1d575 100644
--- a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
+++ b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
@@ -29,6 +29,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
public class WallpaperSuggestionActivity extends Activity {
@Override
@@ -39,6 +41,10 @@ public class WallpaperSuggestionActivity extends Activity {
.setClassName(getString(R.string.config_wallpaper_picker_package),
getString(R.string.config_wallpaper_picker_class))
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+
+ // passing the necessary extra to next page
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+
if (pm.resolveActivity(intent, 0) != null) {
startActivity(intent);
} else {
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 921552d6415..d1df7f0d6f4 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -21,6 +21,7 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
@@ -74,6 +75,9 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
/** Delayed time to stop scanning wifi. */
private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
+ @VisibleForTesting
+ final static String EXTRA_APP_NAME = "com.android.settings.wifi.extra.APP_NAME";
+
private List mAccessPointList;
private FilterWifiTracker mFilterWifiTracker;
private AccessPointAdapter mDialogAdapter;
@@ -93,7 +97,8 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
final View customTitle = inflater.inflate(R.layout.network_request_dialog_title, null);
final TextView title = customTitle.findViewById(R.id.network_request_title_text);
- title.setText(R.string.network_connection_request_dialog_title);
+ title.setText(getTitle());
+
final ProgressBar progressBar = customTitle.findViewById(
R.id.network_request_title_progress);
progressBar.setVisibility(View.VISIBLE);
@@ -115,6 +120,16 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
return dialog;
}
+ private String getTitle() {
+ final Intent intent = getActivity().getIntent();
+ String appName = "";
+ if (intent != null) {
+ appName = intent.getStringExtra(EXTRA_APP_NAME);
+ }
+
+ return getString(R.string.network_connection_request_dialog_title, appName);
+ }
+
@NonNull
List getAccessPointList() {
// Initials list for adapter, in case of display crashing.
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index b0d09e4c12a..a679d372919 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -63,6 +63,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.settings.ProxySelector;
import com.android.settings.R;
+import com.android.settings.wifi.details.WifiPrivacyPreferenceController;
import com.android.settingslib.Utils;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.wifi.AccessPoint;
@@ -251,8 +252,6 @@ public class WifiConfigController implements TextWatcher,
com.android.settings.core.FeatureFlags.WIFI_MAC_RANDOMIZATION)) {
View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
privacySettingsLayout.setVisibility(View.VISIBLE);
- // Set default value
- mPrivacySettingsSpinner.setSelection(WifiConfiguration.RANDOMIZATION_PERSISTENT);
}
mHiddenSettingsSpinner.setOnItemSelectedListener(this);
mHiddenWarningView = mView.findViewById(R.id.hidden_settings_warning);
@@ -281,7 +280,12 @@ public class WifiConfigController implements TextWatcher,
mHiddenSettingsSpinner.setSelection(config.hiddenSSID
? HIDDEN_NETWORK
: NOT_HIDDEN_NETWORK);
- mPrivacySettingsSpinner.setSelection(config.macRandomizationSetting);
+
+ final int prefMacValue =
+ WifiPrivacyPreferenceController.translateMacRandomizedValueToPrefValue(
+ config.macRandomizationSetting);
+ mPrivacySettingsSpinner.setSelection(prefMacValue);
+
if (config.getIpAssignment() == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
@@ -766,7 +770,10 @@ public class WifiConfigController implements TextWatcher,
}
if (mPrivacySettingsSpinner != null) {
- config.macRandomizationSetting = mPrivacySettingsSpinner.getSelectedItemPosition();
+ final int macValue =
+ WifiPrivacyPreferenceController.translatePrefValueToMacRandomizedValue(
+ mPrivacySettingsSpinner.getSelectedItemPosition());
+ config.macRandomizationSetting = macValue;
}
return config;
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 1105f742c09..27db7cd85f9 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -290,7 +290,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
.setButton2OnClickListener(view -> signIntoNetwork())
.setButton3Text(R.string.share)
.setButton3Icon(R.drawable.ic_qrcode_24dp)
- .setButton3OnClickListener(view -> shareNetwork());
+ .setButton3OnClickListener(view -> shareNetwork())
+ .setButton3Visible(WifiDppUtils.isSuportConfigurator(mContext, mAccessPoint));
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
@@ -558,10 +559,15 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
/**
* Show QR code to share the network represented by this preference.
*/
- public void launchQRCodeGenerator() {
- Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntent(mContext, mWifiManager,
+ public void launchWifiDppConfiguratorActivity() {
+ final Intent intent = WifiDppUtils.getConfiguratorIntentOrNull(mContext, mWifiManager,
mAccessPoint);
- mContext.startActivity(intent);
+
+ if (intent == null) {
+ Log.e(TAG, "Launch Wi-Fi DPP configurator with a wrong Wi-Fi network!");
+ } else {
+ mContext.startActivity(intent);
+ }
}
/**
@@ -584,7 +590,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
WifiNetworkDetailsFragment.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
} else {
- launchQRCodeGenerator();
+ launchWifiDppConfiguratorActivity();
}
}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 2f45526e3a6..5ac0d284b46 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -152,7 +152,7 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
&& resultCode == Activity.RESULT_OK) {
- mWifiDetailPreferenceController.launchQRCodeGenerator();
+ mWifiDetailPreferenceController.launchWifiDppConfiguratorActivity();
}
}
}
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index 3bcdc5fad9c..a20adc9b2ee 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -85,15 +85,29 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im
return WifiConfiguration.RANDOMIZATION_PERSISTENT;
}
- private final int PREF_RANDOMIZATION_PERSISTENT = 0;
- private final int PREF_RANDOMIZATION_NONE = 1;
- @VisibleForTesting
- protected int translateMacRandomizedValueToPrefValue(int macRandomized) {
- if (macRandomized == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
- return PREF_RANDOMIZATION_PERSISTENT;
- } else {
- return PREF_RANDOMIZATION_NONE;
- }
+ private static final int PREF_RANDOMIZATION_PERSISTENT = 0;
+ private static final int PREF_RANDOMIZATION_NONE = 1;
+
+ /**
+ * Returns preference index value.
+ *
+ * @param macRandomized is mac randomized value
+ * @return index value of preference
+ */
+ public static int translateMacRandomizedValueToPrefValue(int macRandomized) {
+ return (macRandomized == WifiConfiguration.RANDOMIZATION_PERSISTENT)
+ ? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE;
+ }
+
+ /**
+ * Returns mac randomized value.
+ *
+ * @param prefMacRandomized is preference index value
+ * @return mac randomized value
+ */
+ public static int translatePrefValueToMacRandomizedValue(int prefMacRandomized) {
+ return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT)
+ ? WifiConfiguration.RANDOMIZATION_PERSISTENT : WifiConfiguration.RANDOMIZATION_NONE;
}
private void updateSummary(DropDownPreference preference, int macRandomized) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index f2ca24edaf8..d0a96384d7c 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -84,9 +84,18 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.next_label);
- item.setIcon(R.drawable.ic_scan_24dp);
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
+ MenuItem menuItem;
+ if (wifiNetworkConfig.isSupportConfiguratorQrCodeScanner(getActivity())) {
+ menuItem = menu.add(0, Menu.FIRST, 0, R.string.next_label);
+ menuItem.setIcon(R.drawable.ic_scan_24dp);
+ menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ } else {
+ menuItem = menu.findItem(Menu.FIRST);
+ if (menuItem != null) {
+ menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ }
+ }
super.onCreateOptionsMenu(menu, inflater);
}
@@ -116,11 +125,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
mQrCodeView = view.findViewById(R.id.qrcode_view);
mHeaderIcon.setImageResource(R.drawable.ic_qrcode_24dp);
- WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
- .getWifiNetworkConfig();
- if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
- throw new IllegalStateException("Invalid Wi-Fi network for configuring");
- }
+ final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
mTitle.setText(R.string.wifi_dpp_share_wifi);
mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
wifiNetworkConfig.getSsid()));
@@ -139,4 +144,14 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
Log.e(TAG, "Error generatting QR code bitmap " + e);
}
}
+
+ WifiNetworkConfig getWifiNetworkConfigFromHostActivity() {
+ final WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+ .getWifiNetworkConfig();
+ if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+ throw new IllegalStateException("Invalid Wi-Fi network for configuring");
+ }
+
+ return wifiNetworkConfig;
+ }
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index ef7a1c9fdc2..e1b8ead321e 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -134,26 +134,36 @@ public class WifiDppUtils {
private static String getSecurityString(AccessPoint accessPoint) {
switch(accessPoint.getSecurity()) {
case AccessPoint.SECURITY_WEP:
- return "WEP";
+ return WifiQrCode.SECURITY_WEP;
case AccessPoint.SECURITY_PSK:
- return "WPA";
+ return WifiQrCode.SECURITY_WPA;
+ case AccessPoint.SECURITY_SAE:
+ return WifiQrCode.SECURITY_SAE;
default:
- return "nopass";
+ return WifiQrCode.SECURITY_NO_PASSWORD;
}
}
/**
- * Returns an intent to launch QR code generator.
+ * Returns an intent to launch QR code generator or scanner according to the Wi-Fi network
+ * security. It may return null if the security is not supported by QR code generator nor
+ * scanner.
*
* @param context The context to use for the content resolver
* @param wifiManager An instance of {@link WifiManager}
* @param accessPoint An instance of {@link AccessPoint}
* @return Intent for launching QR code generator
*/
- public static Intent getConfiguratorQrCodeGeneratorIntent(Context context,
+ public static Intent getConfiguratorIntentOrNull(Context context,
WifiManager wifiManager, AccessPoint accessPoint) {
final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
- intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ if (isSupportConfiguratorQrCodeGenerator(accessPoint)) {
+ intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ } else if (isSupportConfiguratorQrCodeScanner(context, accessPoint)) {
+ intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+ } else {
+ return null;
+ }
final WifiConfiguration wifiConfig = accessPoint.getConfig();
final String ssid = removeFirstAndLastDoubleQuotes(wifiConfig.SSID);
@@ -183,4 +193,43 @@ public class WifiDppUtils {
return intent;
}
+
+ /**
+ * Android Q supports Wi-Fi configurator by:
+ *
+ * 1. QR code generator of ZXing's Wi-Fi network config format.
+ * and
+ * 2. QR code scanner of Wi-Fi DPP QR code format.
+ */
+ public static boolean isSuportConfigurator(Context context, AccessPoint accessPoint) {
+ return isSupportConfiguratorQrCodeScanner(context, accessPoint) ||
+ isSupportConfiguratorQrCodeGenerator(accessPoint);
+ }
+
+ private static boolean isSupportConfiguratorQrCodeScanner(Context context,
+ AccessPoint accessPoint) {
+ if (!isWifiDppEnabled(context)) {
+ return false;
+ }
+
+ // DPP 1.0 only supports SAE and PSK.
+ final int security = accessPoint.getSecurity();
+ if (security == AccessPoint.SECURITY_SAE || security == AccessPoint.SECURITY_PSK) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean isSupportConfiguratorQrCodeGenerator(AccessPoint accessPoint) {
+ // QR code generator produces QR code with ZXing's Wi-Fi network config format,
+ // it supports PSK and WEP and non security
+ final int security = accessPoint.getSecurity();
+ if (security == AccessPoint.SECURITY_PSK || security == AccessPoint.SECURITY_WEP ||
+ security == AccessPoint.SECURITY_NONE) {
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
index 915e90def21..08b54204f10 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -17,6 +17,7 @@
package com.android.settings.wifi.dpp;
import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_NO_PASSWORD;
+import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_SAE;
import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WEP;
import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WPA;
@@ -208,6 +209,19 @@ public class WifiNetworkConfig {
wifiManager.connect(wifiConfiguration, listener);
}
+ public boolean isSupportConfiguratorQrCodeScanner(Context context) {
+ if (!WifiDppUtils.isWifiDppEnabled(context)) {
+ return false;
+ }
+
+ // DPP 1.0 only supports SAE and PSK.
+ if (SECURITY_SAE.equals(mSecurity) || SECURITY_WPA.equals(mSecurity)) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* This is a simplified method from {@code WifiConfigController.getConfig()}
*/
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
index 7ea4906cc78..0a7a08c8267 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
@@ -48,7 +48,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
private static final String TAG = "WifiNetworkListFragment";
private static final String WIFI_CONFIG_KEY = "wifi_config_key";
- private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list";
private static final String PREF_KEY_ACCESS_POINTS = "access_points";
static final int ADD_NETWORK_REQUEST = 1;
@@ -277,7 +276,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
// AccessPoints are sorted by the WifiTracker
final List accessPoints = mWifiTracker.getAccessPoints();
- boolean hasAvailableAccessPoints = false;
mAccessPointsPreferenceCategory.setVisible(true);
cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
@@ -299,7 +297,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
return;
}
- hasAvailableAccessPoints = true;
final AccessPointPreference pref = (AccessPointPreference) getCachedPreference(key);
if (pref != null) {
pref.setOrder(index);
@@ -317,15 +314,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
removeCachedPrefs(mAccessPointsPreferenceCategory);
mAddPreference.setOrder(index);
mAccessPointsPreferenceCategory.addPreference(mAddPreference);
-
- if (!hasAvailableAccessPoints) {
- final Preference pref = new Preference(getPrefContext());
- pref.setSelectable(false);
- pref.setSummary(R.string.wifi_empty_list_wifi_on);
- pref.setOrder(index++);
- pref.setKey(PREF_KEY_EMPTY_WIFI_LIST);
- mAccessPointsPreferenceCategory.addPreference(pref);
- }
}
private AccessPointPreference createAccessPointPreference(AccessPoint accessPoint) {
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
index 5ccb81e0203..d3f8ebf5aa5 100644
--- a/src/com/android/settings/wifi/dpp/WifiQrCode.java
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -67,6 +67,7 @@ public class WifiQrCode {
public static final String SECURITY_NO_PASSWORD = "nopass";
public static final String SECURITY_WEP = "WEP";
public static final String SECURITY_WPA = "WPA";
+ public static final String SECURITY_SAE = "WPA3";
private String mQrCode;
diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index 1c79c1d92b4..88fa8b298ef 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -292,11 +292,12 @@ public class WifiSlice implements CustomSliceable {
@Override
public void onWifiStateChanged(int state) {
- mContext.getContentResolver().notifyChange(getUri(), null);
+ notifySliceChange();
}
@Override
public void onConnectedChanged() {
+ notifySliceChange();
}
@Override
diff --git a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
index bf4dec6f02f..c6a48a889a9 100644
--- a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
@@ -32,6 +32,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.ArraySet;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -45,6 +46,9 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowDevicePolicyManager;
+import java.util.Arrays;
+import java.util.Collections;
+
@RunWith(RobolectricTestRunner.class)
public class CrossProfileCalendarPreferenceControllerTest {
@@ -123,7 +127,17 @@ public class CrossProfileCalendarPreferenceControllerTest {
@Test
public void updateState_somePackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
dpm.setProfileOwner(TEST_COMPONENT_NAME);
- dpm.addCrossProfileCalendarPackage(TEST_COMPONENT_NAME, TEST_PACKAGE_NAME);
+ dpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mController.updateState(mPreference);
+ verify(mPreference).setDisabledByAdmin(null);
+ }
+
+ @Test
+ public void updateState_allPackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
+ dpm.setProfileOwner(TEST_COMPONENT_NAME);
+ dpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME, null);
mController.updateState(mPreference);
verify(mPreference).setDisabledByAdmin(null);
diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
index aab2156de08..3fd43695396 100644
--- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
@@ -38,6 +38,7 @@ import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.PowerManager;
@@ -102,10 +103,13 @@ public class RecentAppsPreferenceControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState);
doReturn(mUsageStatsManager).when(mContext).getSystemService(Context.USAGE_STATS_SERVICE);
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+ when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {});
mController = new RecentAppsPreferenceController(mContext, mAppState, null);
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
@@ -350,6 +354,57 @@ public class RecentAppsPreferenceControllerTest {
verify(mCategory).addPreference(argThat(summaryMatches("0 minutes ago")));
}
+ @Test
+ public void displayPreference_shouldNotShowHiddenSystemModule() {
+ final List stats = new ArrayList<>();
+ // Regular app.
+ final UsageStats stat1 = new UsageStats();
+ stat1.mLastTimeUsed = System.currentTimeMillis();
+ stat1.mPackageName = "com.foo.bar";
+ stats.add(stat1);
+
+ // Hidden system module.
+ final UsageStats stat2 = new UsageStats();
+ stat2.mLastTimeUsed = System.currentTimeMillis() + 200;
+ stat2.mPackageName = "com.foo.hidden";
+ stats.add(stat2);
+
+ ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class);
+ ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class);
+ stat1Entry.info = mApplicationInfo;
+ stat2Entry.info = mApplicationInfo;
+
+ when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry);
+ when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry);
+
+ final ModuleInfo moduleInfo1 = new ModuleInfo();
+ moduleInfo1.setPackageName(stat1.mPackageName);
+ moduleInfo1.setHidden(false);
+
+ final ModuleInfo moduleInfo2 = new ModuleInfo();
+ moduleInfo2.setPackageName(stat2.mPackageName);
+ moduleInfo2.setHidden(true);
+
+ ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
+ final List modules = new ArrayList<>();
+ modules.add(moduleInfo2);
+ when(mPackageManager.getInstalledModules(anyInt() /* flags */))
+ .thenReturn(modules);
+
+ when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
+ .thenReturn(new ResolveInfo());
+ when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
+ .thenReturn(stats);
+
+ mController.displayPreference(mScreen);
+
+ // Only add stat1. stat2 is skipped because it is hidden module.
+ final ArgumentCaptor prefCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(mCategory).addPreference(prefCaptor.capture());
+ final Preference pref = prefCaptor.getValue();
+ assertThat(pref.getKey()).isEqualTo(stat1.mPackageName);
+ }
+
private static ArgumentMatcher summaryMatches(String expected) {
return preference -> TextUtils.equals(expected, preference.getSummary());
}
diff --git a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
index e2035e33c42..75302d837c3 100644
--- a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
@@ -20,11 +20,16 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEA
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -55,6 +60,8 @@ public class SpecialAppAccessPreferenceControllerTest {
private ApplicationsState.Session mSession;
@Mock
private PreferenceScreen mScreen;
+ @Mock
+ private PackageManager mPackageManager;
private SpecialAppAccessPreferenceController mController;
private Preference mPreference;
@@ -62,8 +69,11 @@ public class SpecialAppAccessPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getApplicationContext()).thenReturn(mContext);
ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{0});
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(new ArrayList()).when(mPackageManager).getInstalledModules(anyInt());
mController = new SpecialAppAccessPreferenceController(mContext, "test_key");
mPreference = new Preference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
index 719b7378cd2..89beede13a5 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
@@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -28,6 +29,7 @@ import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
+import android.permission.PermissionControllerManager;
import androidx.preference.Preference;
@@ -38,6 +40,7 @@ import com.android.settings.applications.DefaultAppSettings;
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;
import org.robolectric.Robolectric;
@@ -48,6 +51,8 @@ import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowUserManager;
import java.util.Collections;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUserManager.class)
@@ -60,6 +65,8 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
@Mock
private RoleManager mRoleManager;
@Mock
+ private PermissionControllerManager mPermissionControllerManager;
+ @Mock
private Preference mPreference;
private Activity mActivity;
@@ -71,7 +78,10 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ shadowApplication.setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
+ mPermissionControllerManager);
mActivity = Robolectric.setupActivity(Activity.class);
mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class));
mController = new TestRolePreferenceController(mActivity);
@@ -79,6 +89,12 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
mLegacyController = new TestLegacyPreferenceController(mActivity);
}
+ @Test
+ public void constructor_callsIsApplicationQualifiedForRole() {
+ verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
+ TEST_PACKAGE_NAME), any(Executor.class), any(Consumer.class));
+ }
+
@Test
public void getAvailabilityStatus_isManagedProfile_shouldReturnDisabled() {
mShadowUserManager.setManagedProfile(true);
@@ -88,23 +104,38 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
}
@Test
- public void getAvailabilityStatus_roleIsAvailable_shouldReturnAvailable() {
- mShadowUserManager.setManagedProfile(false);
- when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(true);
-
+ public void
+ getAvailabilityStatus_noCallbackForIsApplicationNotQualifiedForRole_shouldReturnUnsupported() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
- DefaultAppShortcutPreferenceControllerBase.AVAILABLE);
+ DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE);
}
@Test
- public void getAvailabilityStatus_roleNotAvailable_shouldReturnDisabled() {
- mShadowUserManager.setManagedProfile(false);
- when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(false);
+ public void getAvailabilityStatus_applicationIsNotQualifiedForRole_shouldReturnUnsupported() {
+ final ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass(
+ Consumer.class);
+ verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
+ TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
+ final Consumer callback = callbackCaptor.getValue();
+ callback.accept(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE);
}
+ @Test
+ public void getAvailabilityStatus_applicationIsQualifiedForRole_shouldReturnAvailable() {
+ final ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass(
+ Consumer.class);
+ verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
+ TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
+ final Consumer callback = callbackCaptor.getValue();
+ callback.accept(true);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ DefaultAppShortcutPreferenceControllerBase.AVAILABLE);
+ }
+
@Test
public void updateState_isRoleHolder_shouldSetSummaryToYes() {
when(mRoleManager.getRoleHolders(eq(TEST_ROLE_NAME))).thenReturn(Collections.singletonList(
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
index 6c8435fa29a..b31a10d75dd 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
@@ -18,11 +18,17 @@ package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
+import android.content.Context;
+import android.permission.PermissionControllerManager;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class)
public class DefaultSmsShortcutPreferenceControllerTest {
@@ -30,10 +36,16 @@ public class DefaultSmsShortcutPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String PREFERENCE_KEY = "default_sms_app";
+ @Mock
+ private PermissionControllerManager mPermissionControllerManager;
+
private DefaultSmsShortcutPreferenceController mController;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
+ mPermissionControllerManager);
mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME);
}
diff --git a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPickerTest.java b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPickerTest.java
deleted file mode 100644
index 3804d6d32f9..00000000000
--- a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPickerTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.assist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.provider.Settings;
-
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowActivityManager;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class DefaultAssistPickerTest {
-
- private static ComponentName sTestAssist;
-
- @BeforeClass
- public static void beforeClass() {
- sTestAssist = new ComponentName("com.android.settings", "assist");
- }
-
- private Context mContext;
- private DefaultAssistPicker mPicker;
- private ShadowActivityManager mShadowActivityManager;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mShadowActivityManager = Shadow.extract(mContext.getSystemService(ActivityManager.class));
- mPicker = spy(new DefaultAssistPicker());
- mPicker.onAttach(mContext);
- doReturn(mContext).when(mPicker).getContext();
- }
-
- @Test
- public void setDefaultAppKey_shouldUpdateDefaultAssist() {
- final List assistants = new ArrayList<>();
- assistants.add(new DefaultAssistPicker.Info(sTestAssist));
- ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
- mPicker.setDefaultKey(sTestAssist.flattenToString());
-
- assertThat(Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT))
- .isEqualTo(sTestAssist.flattenToString());
- assertThat(mPicker.getDefaultKey()).isEqualTo(sTestAssist.flattenToString());
- }
-
- @Test
- public void setDefaultAppKey_noAvailableAssist_shouldClearDefaultAssist() {
- final List assistants = new ArrayList<>();
- ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
- mPicker.setDefaultKey(sTestAssist.flattenToString());
-
- assertThat(Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT))
- .isEmpty();
- assertThat(mPicker.getDefaultKey()).isNull();
- }
-
- @Test
- public void setDefaultAppKeyToNull_shouldClearDefaultAssist() {
- final List assistants = new ArrayList<>();
- assistants.add(new DefaultAssistPicker.Info(sTestAssist));
- ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
- mPicker.setDefaultKey(null);
-
- assertThat(Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT))
- .isEmpty();
- assertThat(mPicker.getDefaultKey()).isNull();
- }
-
- @Test
- public void addAssistService_lowRamDevice_shouldDoNothing() {
- mShadowActivityManager.setIsLowRamDevice(true);
- mPicker.addAssistServices();
-
- assertThat(mPicker.mAvailableAssistants).hasSize(0);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
index 67c03d56b79..8be6b3084af 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -38,7 +38,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
@@ -137,7 +137,7 @@ public class FingerprintEnrollFindSensorTest {
@Test
public void clickSkip_shouldReturnResultSkip() {
PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
assertThat(shadowActivity.getResultCode()).named("result code")
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
index 82124f91d1c..9fa6099cbea 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
@@ -32,7 +32,7 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.Before;
import org.junit.Test;
@@ -68,7 +68,7 @@ public class FingerprintSuggestionActivityTest {
PartnerCustomizationLayout layout =
mController.get().findViewById(R.id.setup_wizard_layout);
final Button cancelButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(cancelButton.getText().toString()).isEqualTo("Cancel");
assertThat(cancelButton.getVisibility()).named("Cancel visible").isEqualTo(View.VISIBLE);
cancelButton.performClick();
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index b112c8a5f13..a198d86a814 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -33,7 +33,7 @@ import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
@@ -75,7 +75,7 @@ public class SetupFingerprintEnrollFindSensorTest {
intent).setup().get();
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().performClick();
final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
index 12bf1e2ca9a..c8177491745 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
@@ -38,7 +38,7 @@ import com.android.settings.testutils.shadow.ShadowStorageManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
@@ -89,7 +89,7 @@ public class SetupFingerprintEnrollIntroductionTest {
PartnerCustomizationLayout layout =
mController.get().findViewById(R.id.setup_wizard_layout);
final Button skipButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
skipButton.performClick();
@@ -108,7 +108,7 @@ public class SetupFingerprintEnrollIntroductionTest {
PartnerCustomizationLayout layout =
mController.get().findViewById(R.id.setup_wizard_layout);
final Button skipButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
skipButton.performClick();
@@ -152,7 +152,7 @@ public class SetupFingerprintEnrollIntroductionTest {
SetupFingerprintEnrollIntroduction activity = mController.create().resume().get();
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
final Button skipButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
getShadowKeyguardManager().setIsKeyguardSecure(true);
skipButton.performClick();
@@ -169,7 +169,7 @@ public class SetupFingerprintEnrollIntroductionTest {
SetupFingerprintEnrollIntroduction activity = mController.create().resume().get();
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
final Button skipButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
skipButton.performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
@@ -213,7 +213,7 @@ public class SetupFingerprintEnrollIntroductionTest {
SetupFingerprintEnrollIntroduction activity = mController.get();
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getPrimaryButtonView().performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
index 1da97f5d520..b6bbe8ad6fc 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
@@ -15,6 +15,8 @@
*/
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
+import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
@@ -101,7 +103,8 @@ public class UsbConnectionBroadcastReceiverTest {
final Intent intent = new Intent();
intent.setAction(UsbManager.ACTION_USB_PORT_CHANGED);
final UsbPortStatus status = new UsbPortStatus(0, POWER_ROLE_SINK,
- DATA_ROLE_DEVICE, 0);
+ DATA_ROLE_DEVICE, 0, CONTAMINANT_PROTECTION_NONE,
+ CONTAMINANT_DETECTION_NOT_SUPPORTED);
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, status);
mReceiver.onReceive(mContext, intent);
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index 66f916e9962..79c3ad10cbf 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.NetworkPolicyManager;
+import android.telephony.SubscriptionManager;
import androidx.fragment.app.FragmentActivity;
@@ -50,6 +51,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowSubscriptionManager;
@Config(shadows = {
ShadowUtils.class,
@@ -114,10 +116,11 @@ public class DataUsageSummaryTest {
}
@Test
+ @Config(shadows = ShadowSubscriptionManager.class)
public void configuration_withSim_shouldShowMobileAndWifi() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
- ShadowDataUsageUtils.DEFAULT_SUBSCRIPTION_ID = 1;
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(1);
ShadowDataUsageUtils.HAS_SIM = true;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
@@ -170,4 +173,26 @@ public class DataUsageSummaryTest {
verify(dataUsageSummary).addWifiSection();
verify(dataUsageSummary, never()).addMobileSection(anyInt());
}
+
+ @Test
+ @Config(shadows = ShadowSubscriptionManager.class)
+ public void configuration_invalidDataSusbscription_shouldShowWifiSectionOnly() {
+ ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
+ ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+ ShadowDataUsageUtils.HAS_SIM = false;
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
+ doReturn(mContext).when(dataUsageSummary).getContext();
+
+ doReturn(true).when(dataUsageSummary).removePreference(anyString());
+ doNothing().when(dataUsageSummary).addWifiSection();
+ doNothing().when(dataUsageSummary).addMobileSection(1);
+
+ dataUsageSummary.onCreate(null);
+
+ verify(dataUsageSummary).addWifiSection();
+ verify(dataUsageSummary, never()).addMobileSection(anyInt());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java
new file mode 100644
index 00000000000..e5958aab550
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 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.deviceinfo.firmwareversion;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ModuleVersionDialogControllerTest {
+
+ @Mock
+ private FirmwareVersionDialogFragment mDialog;
+ @Mock
+ private PackageManager mPackageManager;
+
+ private Context mContext;
+ private ModuleVersionDialogController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mDialog.getContext()).thenReturn(mContext);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mController = new ModuleVersionDialogController(mDialog);
+ }
+
+ @Test
+ public void initialize_noMainlineModuleProvider_shouldRemoveSettingFromDialog() {
+ when(mContext.getString(
+ com.android.internal.R.string.config_defaultModuleMetadataProvider)).thenReturn(null);
+
+ mController.initialize();
+
+ verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_LABEL_ID);
+ verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_VALUE_ID);
+ }
+
+ @Test
+ public void initialize_noMainlineModulePackageInfo_shouldRemoveSettingFromDialog()
+ throws PackageManager.NameNotFoundException {
+ final String provider = "test.provider";
+ when(mContext.getString(
+ com.android.internal.R.string.config_defaultModuleMetadataProvider))
+ .thenReturn(provider);
+ when(mPackageManager.getPackageInfo(eq(provider), anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException());
+
+ mController.initialize();
+
+ verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_LABEL_ID);
+ verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_VALUE_ID);
+ }
+
+ @Test
+ public void initialize_hasMainlineModulePackageInfo_shouldshouldSetDialogTextToMainlineVersion()
+ throws PackageManager.NameNotFoundException {
+ final String provider = "test.provider";
+ final String version = "test version 123";
+ final PackageInfo info = new PackageInfo();
+ info.versionName = version;
+ when(mContext.getString(
+ com.android.internal.R.string.config_defaultModuleMetadataProvider))
+ .thenReturn(provider);
+ when(mPackageManager.getPackageInfo(eq(provider), anyInt())).thenReturn(info);
+
+ mController.initialize();
+
+ verify(mDialog).setText(mController.MODULE_VERSION_VALUE_ID, version);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
index e7f025f7be4..cf7e34f5404 100644
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
@@ -23,10 +23,10 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
import androidx.preference.Preference;
-import com.android.internal.app.ColorDisplayController;
import com.android.settings.R;
import org.junit.Before;
@@ -41,7 +41,7 @@ import org.robolectric.RuntimeEnvironment;
public class ColorModePreferenceControllerTest {
@Mock
- private ColorDisplayController mColorDisplayController;
+ private ColorDisplayManager mColorDisplayManager;
private Context mContext;
private Preference mPreference;
@@ -53,13 +53,13 @@ public class ColorModePreferenceControllerTest {
mContext = RuntimeEnvironment.application;
mController = spy(new ColorModePreferenceController(mContext, "test"));
mPreference = new Preference(mContext);
- doReturn(mColorDisplayController).when(mController).getColorDisplayController();
+ doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
}
@Test
public void updateState_colorModeAutomatic_shouldSetSummaryToAutomatic() {
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_AUTOMATIC);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
mController.updateState(mPreference);
@@ -69,8 +69,8 @@ public class ColorModePreferenceControllerTest {
@Test
public void updateState_colorModeSaturated_shouldSetSummaryToSaturated() {
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_SATURATED);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
mController.updateState(mPreference);
@@ -80,8 +80,8 @@ public class ColorModePreferenceControllerTest {
@Test
public void updateState_colorModeBoosted_shouldSetSummaryToBoosted() {
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_BOOSTED);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_BOOSTED);
mController.updateState(mPreference);
@@ -91,8 +91,8 @@ public class ColorModePreferenceControllerTest {
@Test
public void updateState_colorModeNatural_shouldSetSummaryToNatural() {
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_NATURAL);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
index a87dddd2aad..54e8e4de186 100644
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
@@ -25,13 +25,12 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.hardware.display.ColorDisplayManager;
import android.os.Bundle;
-import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.internal.app.ColorDisplayController;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
@@ -59,17 +58,14 @@ public class ColorModePreferenceFragmentTest {
private ColorModePreferenceFragment mFragment;
@Mock
- private ColorDisplayController mController;
-
- @Mock
- private FragmentActivity mActivity;
+ private ColorDisplayManager mManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mFragment = spy(new ColorModePreferenceFragment());
- ReflectionHelpers.setField(mFragment, "mController", mController);
+ ReflectionHelpers.setField(mFragment, "mColorDisplayManager", mManager);
}
@After
@@ -88,10 +84,10 @@ public class ColorModePreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
SettingsShadowResources.overrideResource(
com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayController.COLOR_MODE_NATURAL,
- ColorDisplayController.COLOR_MODE_BOOSTED,
- ColorDisplayController.COLOR_MODE_SATURATED,
- ColorDisplayController.COLOR_MODE_AUTOMATIC
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_BOOSTED,
+ ColorDisplayManager.COLOR_MODE_SATURATED,
+ ColorDisplayManager.COLOR_MODE_AUTOMATIC
});
List extends CandidateInfo> candidates = mFragment.getCandidates();
@@ -121,8 +117,8 @@ public class ColorModePreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
SettingsShadowResources.overrideResource(
com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayController.COLOR_MODE_NATURAL,
- ColorDisplayController.COLOR_MODE_AUTOMATIC
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_AUTOMATIC
});
List extends CandidateInfo> candidates = mFragment.getCandidates();
@@ -138,9 +134,9 @@ public class ColorModePreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
SettingsShadowResources.overrideResource(
com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayController.COLOR_MODE_NATURAL,
- ColorDisplayController.COLOR_MODE_BOOSTED,
- ColorDisplayController.COLOR_MODE_SATURATED,
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_BOOSTED,
+ ColorDisplayManager.COLOR_MODE_SATURATED,
});
List extends CandidateInfo> candidates = mFragment.getCandidates();
@@ -155,8 +151,8 @@ public class ColorModePreferenceFragmentTest {
@Test
public void getKey_natural() {
- when(mController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_NATURAL);
+ when(mManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
assertThat(mFragment.getDefaultKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
@@ -164,8 +160,8 @@ public class ColorModePreferenceFragmentTest {
@Test
public void getKey_boosted() {
- when(mController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_BOOSTED);
+ when(mManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_BOOSTED);
assertThat(mFragment.getDefaultKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
@@ -173,8 +169,8 @@ public class ColorModePreferenceFragmentTest {
@Test
public void getKey_saturated() {
- when(mController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_SATURATED);
+ when(mManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mFragment.getDefaultKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
@@ -182,8 +178,8 @@ public class ColorModePreferenceFragmentTest {
@Test
public void getKey_automatic() {
- when(mController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_AUTOMATIC);
+ when(mManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
assertThat(mFragment.getDefaultKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
@@ -192,25 +188,25 @@ public class ColorModePreferenceFragmentTest {
@Test
public void setKey_natural() {
mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- verify(mController).setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
}
@Test
public void setKey_boosted() {
mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
- verify(mController).setColorMode(ColorDisplayController.COLOR_MODE_BOOSTED);
+ verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
}
@Test
public void setKey_saturated() {
mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
- verify(mController).setColorMode(ColorDisplayController.COLOR_MODE_SATURATED);
+ verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
}
@Test
public void setKey_automatic() {
mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
- verify(mController).setColorMode(ColorDisplayController.COLOR_MODE_AUTOMATIC);
+ verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
}
@Test
@@ -237,11 +233,4 @@ public class ColorModePreferenceFragmentTest {
assertThat(preferenceCaptor.getValue()).isEqualTo(mockPreview);
}
-
- @Test
- public void onAccessibilityTransformChanged_toggles() {
- when(mFragment.getActivity()).thenReturn(mActivity);
- mFragment.onAccessibilityTransformChanged(true /* state */);
- verify(mActivity).onBackPressed();
- }
}
diff --git a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
index de560373be6..59820e61a99 100644
--- a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
@@ -6,9 +6,9 @@ import static org.mockito.Mockito.when;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
-import com.android.internal.app.ColorDisplayController;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
import org.junit.Before;
@@ -30,7 +30,7 @@ public class DisplayWhiteBalancePreferenceControllerTest {
private DisplayWhiteBalancePreferenceController mController;
@Mock
- private ColorDisplayController mColorDisplayController;
+ private ColorDisplayManager mColorDisplayManager;
@After
public void tearDown() {
@@ -43,15 +43,15 @@ public class DisplayWhiteBalancePreferenceControllerTest {
mContext = RuntimeEnvironment.application;
mController = spy(new DisplayWhiteBalancePreferenceController(mContext,
"display_white_balance"));
- doReturn(mColorDisplayController).when(mController).getColorDisplayController();
+ doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
}
@Test
public void isAvailable_configuredAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_NATURAL);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
assertThat(mController.isAvailable()).isTrue();
}
@@ -59,20 +59,20 @@ public class DisplayWhiteBalancePreferenceControllerTest {
public void isAvailable_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_SATURATED);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_NATURAL);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
assertThat(mController.isAvailable()).isFalse();
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayController.getColorMode())
- .thenReturn(ColorDisplayController.COLOR_MODE_SATURATED);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java
index 6e23e5f67fe..e666d61aeac 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java
@@ -15,12 +15,11 @@
package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.provider.Settings.Secure;
+import android.hardware.display.ColorDisplayManager;
import android.view.View;
import androidx.preference.PreferenceScreen;
@@ -47,17 +46,19 @@ public class NightDisplayActivationPreferenceControllerTest {
private PreferenceScreen mScreen;
private LayoutPreference mPreference;
private Context mContext;
- private NightDisplayActivationPreferenceController mController;
+ private ColorDisplayManager mColorDisplayManager;
+ private NightDisplayActivationPreferenceController mPreferenceController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
+ mColorDisplayManager = mContext.getSystemService(ColorDisplayManager.class);
mPreference = new LayoutPreference(mContext, R.layout.night_display_activation_button);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
- mController = new NightDisplayActivationPreferenceController(mContext,
+ mPreferenceController = new NightDisplayActivationPreferenceController(mContext,
"night_display_activation");
- mController.displayPreference(mScreen);
+ mPreferenceController.displayPreference(mScreen);
}
@After
@@ -69,14 +70,14 @@ public class NightDisplayActivationPreferenceControllerTest {
public void isAvailable_configuredAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_nightDisplayAvailable, true);
- assertThat(mController.isAvailable()).isTrue();
+ assertThat(mPreferenceController.isAvailable()).isTrue();
}
@Test
public void isAvailable_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_nightDisplayAvailable, false);
- assertThat(mController.isAvailable()).isFalse();
+ assertThat(mPreferenceController.isAvailable()).isFalse();
}
@Test
@@ -95,25 +96,23 @@ public class NightDisplayActivationPreferenceControllerTest {
@Test
public void onClick_activates() {
- Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 0);
+ mColorDisplayManager.setNightDisplayActivated(false);
final View view = mPreference.findViewById(R.id.night_display_turn_on_button);
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
view.performClick();
- assertThat(Secure.getInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, -1))
- .isEqualTo(1);
+ assertThat(mColorDisplayManager.isNightDisplayActivated()).isEqualTo(true);
}
@Test
public void onClick_deactivates() {
- Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 1);
+ mColorDisplayManager.setNightDisplayActivated(true);
- final View view = mPreference.findViewById(R.id.night_display_turn_on_button);
+ final View view = mPreference.findViewById(R.id.night_display_turn_off_button);
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
view.performClick();
- assertThat(Secure.getInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, -1))
- .isEqualTo(0);
+ assertThat(mColorDisplayManager.isNightDisplayActivated()).isEqualTo(false);
}
}
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayAutoModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayAutoModePreferenceControllerTest.java
index 85d497a1733..de5c81e037a 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplayAutoModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplayAutoModePreferenceControllerTest.java
@@ -17,9 +17,9 @@ package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
import android.provider.Settings.Secure;
-import com.android.internal.app.ColorDisplayController;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
@@ -66,8 +66,8 @@ public class NightDisplayAutoModePreferenceControllerTest {
@Test
public void onPreferenceChange_changesAutoMode() {
mController.onPreferenceChange(null,
- String.valueOf(ColorDisplayController.AUTO_MODE_TWILIGHT));
- assertThat(Secure.getInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE, -1))
- .isEqualTo(ColorDisplayController.AUTO_MODE_TWILIGHT);
+ String.valueOf(ColorDisplayManager.AUTO_MODE_TWILIGHT));
+ assertThat(mContext.getSystemService(ColorDisplayManager.class).getNightDisplayAutoMode())
+ .isEqualTo(ColorDisplayManager.AUTO_MODE_TWILIGHT);
}
}
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayIntensityPreferenceControllerTest.java
index 2edec2ed5b5..2e2d6318683 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplayIntensityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplayIntensityPreferenceControllerTest.java
@@ -17,10 +17,9 @@ package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
import android.provider.Settings.Secure;
-
import com.android.settings.testutils.shadow.SettingsShadowResources;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -33,69 +32,69 @@ import org.robolectric.annotation.Config;
@Config(shadows = SettingsShadowResources.class)
public class NightDisplayIntensityPreferenceControllerTest {
- private Context mContext;
- private NightDisplayIntensityPreferenceController mController;
+ private Context mContext;
+ private NightDisplayIntensityPreferenceController mPreferenceController;
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mController = new NightDisplayIntensityPreferenceController(mContext,
- "night_display_temperature");
- }
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mPreferenceController = new NightDisplayIntensityPreferenceController(mContext,
+ "night_display_temperature");
+ }
- @After
- public void tearDown() {
- SettingsShadowResources.reset();
- }
+ @After
+ public void tearDown() {
+ SettingsShadowResources.reset();
+ }
- @Test
- public void isAvailable_configuredAvailable_isActivated_available() {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_nightDisplayAvailable, true);
- Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 1);
- assertThat(mController.isAvailable()).isTrue();
- }
+ @Test
+ public void isAvailable_configuredAvailable_isActivated_available() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_nightDisplayAvailable, true);
+ Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 1);
+ assertThat(mPreferenceController.isAvailable()).isTrue();
+ }
- @Test
- public void isAvailable_configuredAvailable_isNotActivated_available() {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_nightDisplayAvailable, true);
- Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 0);
- assertThat(mController.isAvailable()).isTrue();
- }
+ @Test
+ public void isAvailable_configuredAvailable_isNotActivated_available() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_nightDisplayAvailable, true);
+ Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_ACTIVATED, 0);
+ assertThat(mPreferenceController.isAvailable()).isTrue();
+ }
- @Test
- public void isAvailable_configuredUnavailable_unavailable() {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_nightDisplayAvailable, false);
- assertThat(mController.isAvailable()).isFalse();
- }
+ @Test
+ public void isAvailable_configuredUnavailable_unavailable() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_nightDisplayAvailable, false);
+ assertThat(mPreferenceController.isAvailable()).isFalse();
+ }
- @Test
- public void onPreferenceChange_changesTemperature() {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.integer.config_nightDisplayColorTemperatureMin, 2950);
- SettingsShadowResources.overrideResource(
- com.android.internal.R.integer.config_nightDisplayColorTemperatureMax, 3050);
- // A slider-adjusted "20" here would be 1/5 from the left / least-intense, i.e. 3030.
- mController.onPreferenceChange(null, 20);
+ @Test
+ public void onPreferenceChange_changesTemperature() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.integer.config_nightDisplayColorTemperatureMin, 2950);
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.integer.config_nightDisplayColorTemperatureMax, 3050);
+ // A slider-adjusted "20" here would be 1/5 from the left / least-intense, i.e. 3030.
+ mPreferenceController.onPreferenceChange(null, 20);
- assertThat(Secure.getInt(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, -1))
- .isEqualTo(3030);
- }
+ assertThat(
+ mContext.getSystemService(ColorDisplayManager.class).getNightDisplayColorTemperature())
+ .isEqualTo(3030);
+ }
- @Test
- public void isSliceableCorrectKey_returnsTrue() {
- final NightDisplayIntensityPreferenceController controller =
- new NightDisplayIntensityPreferenceController(mContext,"night_display_temperature");
- assertThat(controller.isSliceable()).isTrue();
- }
+ @Test
+ public void isSliceableCorrectKey_returnsTrue() {
+ final NightDisplayIntensityPreferenceController controller =
+ new NightDisplayIntensityPreferenceController(mContext, "night_display_temperature");
+ assertThat(controller.isSliceable()).isTrue();
+ }
- @Test
- public void isSliceableIncorrectKey_returnsFalse() {
- final NightDisplayIntensityPreferenceController controller =
- new NightDisplayIntensityPreferenceController(mContext, "bad_key");
- assertThat(controller.isSliceable()).isFalse();
- }
+ @Test
+ public void isSliceableIncorrectKey_returnsFalse() {
+ final NightDisplayIntensityPreferenceController controller =
+ new NightDisplayIntensityPreferenceController(mContext, "bad_key");
+ assertThat(controller.isSliceable()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
index c066e6cdbce..eeaae67f779 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
@@ -3,12 +3,9 @@ package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
-import android.provider.Settings.Secure;
-
-import com.android.internal.app.ColorDisplayController;
+import android.hardware.display.ColorDisplayManager;
import com.android.settings.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,32 +25,32 @@ public class NightDisplayPreferenceControllerTest {
@Test
public void nightDisplaySuggestion_isNotCompleted_ifAutoModeDisabled() {
final Application context = RuntimeEnvironment.application;
- Secure.putInt(context.getContentResolver(),
- Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_DISABLED);
+ context.getSystemService(ColorDisplayManager.class)
+ .setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_DISABLED);
assertThat(NightDisplayPreferenceController.isSuggestionComplete(context)).isFalse();
}
@Test
public void nightDisplaySuggestion_isCompleted_ifAutoModeCustom() {
final Application context = RuntimeEnvironment.application;
- Secure.putInt(context.getContentResolver(),
- Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_CUSTOM);
+ context.getSystemService(ColorDisplayManager.class)
+ .setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME);
assertThat(NightDisplayPreferenceController.isSuggestionComplete(context)).isTrue();
}
@Test
public void nightDisplaySuggestion_isCompleted_ifAutoModeTwilight() {
final Application context = RuntimeEnvironment.application;
- Secure.putInt(context.getContentResolver(),
- Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_TWILIGHT);
+ context.getSystemService(ColorDisplayManager.class)
+ .setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_TWILIGHT);
assertThat(NightDisplayPreferenceController.isSuggestionComplete(context)).isTrue();
}
@Test
- public void nightDisplaySuggestion_isCompleted_ifDisabled() {
+ public void nightDisplaySuggestion_isCompleted_ifSuggestionDisabled() {
final Application context = RuntimeEnvironment.application;
- Secure.putInt(context.getContentResolver(),
- Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_DISABLED);
+ context.getSystemService(ColorDisplayManager.class)
+ .setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_DISABLED);
SettingsShadowResources.overrideResource(R.bool.config_night_light_suggestion_enabled, false);
assertThat(NightDisplayPreferenceController.isSuggestionComplete(context)).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
index e1913a2d304..32829755a62 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
@@ -18,11 +18,15 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -34,6 +38,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
@@ -42,6 +47,10 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BatteryAppListPreferenceControllerTest {
@@ -60,6 +69,10 @@ public class BatteryAppListPreferenceControllerTest {
private InstrumentedPreferenceFragment mFragment;
@Mock
private BatteryUtils mBatteryUtils;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private UserManager mUserManager;
private Context mContext;
private PowerGaugePreference mPreference;
@@ -70,6 +83,11 @@ public class BatteryAppListPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+ when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {});
+
FakeFeatureFactory.setupForTest();
mPreference = new PowerGaugePreference(mContext);
@@ -183,6 +201,21 @@ public class BatteryAppListPreferenceControllerTest {
assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse();
}
+ @Test
+ public void testShouldHideSipper_hiddenSystemModule_returnTrue() {
+ ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
+ final String packageName = "test.hidden.module";
+ final ModuleInfo moduleInfo = new ModuleInfo();
+ moduleInfo.setPackageName(packageName);
+ moduleInfo.setHidden(true);
+ final List modules = new ArrayList<>();
+ modules.add(moduleInfo);
+ when(mBatteryUtils.getPackageName(anyInt() /* uid */)).thenReturn(packageName);
+ when(mPackageManager.getInstalledModules(anyInt() /* flags */)).thenReturn(modules);
+
+ assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isTrue();
+ }
+
@Test
public void testNeverUseFakeData() {
assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse();
diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java
index 3b335587bf9..8cba1defb35 100644
--- a/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java
@@ -36,6 +36,7 @@ import com.android.settingslib.location.RecentLocationAccesses;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -77,6 +78,7 @@ public class RecentLocationAccessPreferenceControllerTest {
/** Verifies the title text, details text are correct, and the click listener is set. */
@Test
+ @Ignore
public void updateState_whenAppListIsEmpty_shouldDisplayTitleTextAndDetailsText() {
doReturn(new ArrayList<>()).when(mRecentLocationApps).getAppListSorted();
mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java
new file mode 100644
index 00000000000..f7a2567dbf1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 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.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.settings.R;
+import com.android.settings.network.SubscriptionUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Arrays;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class DefaultSubscriptionControllerTest {
+ @Mock
+ private SubscriptionManager mManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ListPreference mListPreference;
+ private Context mContext;
+ private DefaultSubscriptionController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mManager);
+ final String key = "prefkey";
+ mController = spy(new TestDefaultSubscriptionController(mContext, key));
+ mListPreference = spy(new ListPreference(mContext));
+ when(mScreen.findPreference(key)).thenReturn(mListPreference);
+ }
+
+ @After
+ public void tearDown() {
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
+ }
+
+ @Test
+ public void getAvailabilityStatus_onlyOneSubscription_notAvailable() {
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(
+ createMockSub(1, "sub1")));
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_twoSubscriptions_isAvailable() {
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(
+ createMockSub(1, "sub1"),
+ createMockSub(2, "sub2")));
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void displayPreference_twoSubscriptionsSub1Default_correctListPreferenceValues() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+
+ final CharSequence entry = mListPreference.getEntry();
+ final String value = mListPreference.getValue();
+ assertThat(entry).isEqualTo("sub1");
+ assertThat(value).isEqualTo("111");
+
+ final CharSequence[] entries = mListPreference.getEntries();
+ assertThat(entries.length).isEqualTo(3);
+ assertThat(entries[0]).isEqualTo("sub1");
+ assertThat(entries[1]).isEqualTo("sub2");
+ assertThat(entries[2]).isEqualTo(mContext.getString(R.string.calls_and_sms_ask_every_time));
+
+ final CharSequence[] entryValues = mListPreference.getEntryValues();
+ assertThat(entryValues.length).isEqualTo(3);
+ assertThat(entryValues[0]).isEqualTo("111");
+ assertThat(entryValues[1]).isEqualTo("222");
+ assertThat(entryValues[2]).isEqualTo(
+ Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+
+ @Test
+ public void displayPreference_twoSubscriptionsSub2Default_correctListPreferenceValues() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub2.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+
+ final CharSequence entry = mListPreference.getEntry();
+ final String value = mListPreference.getValue();
+ assertThat(entry).isEqualTo("sub2");
+ assertThat(value).isEqualTo("222");
+
+ final CharSequence[] entries = mListPreference.getEntries();
+ assertThat(entries.length).isEqualTo(3);
+ assertThat(entries[0]).isEqualTo("sub1");
+ assertThat(entries[1]).isEqualTo("sub2");
+ assertThat(entries[2]).isEqualTo(mContext.getString(R.string.calls_and_sms_ask_every_time));
+
+ final CharSequence[] entryValues = mListPreference.getEntryValues();
+ assertThat(entryValues.length).isEqualTo(3);
+ assertThat(entryValues[0]).isEqualTo("111");
+ assertThat(entryValues[1]).isEqualTo("222");
+ assertThat(entryValues[2]).isEqualTo(
+ Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+
+ @Test
+ public void onPreferenceChange_prefChangedToSub2_callbackCalledCorrectly() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ mListPreference.setValue("222");
+ mController.onPreferenceChange(mListPreference, "222");
+ verify(mController).setDefaultSubscription(eq(222));
+ }
+
+ @Test
+ public void onPreferenceChange_prefChangedToAlwaysAsk_callbackCalledCorrectly() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ mListPreference.setValue(Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ mController.onPreferenceChange(mListPreference,
+ Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ verify(mController).setDefaultSubscription(
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+
+ @Test
+ public void onSubscriptionsChanged_twoSubscriptionsDefaultChanges_selectedEntryGetsUpdated() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ assertThat( mListPreference.getEntry()).isEqualTo("sub1");
+ assertThat(mListPreference.getValue()).isEqualTo("111");
+
+ doReturn(sub2.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+ mController.onSubscriptionsChanged();
+ assertThat( mListPreference.getEntry()).isEqualTo("sub2");
+ assertThat(mListPreference.getValue()).isEqualTo("222");
+ }
+
+ @Test
+ public void onSubscriptionsChanged_goFromTwoSubscriptionsToOne_prefDisappears() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ assertThat(mController.isAvailable()).isTrue();
+ assertThat(mListPreference.isVisible()).isTrue();
+
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+ mController.onSubscriptionsChanged();
+
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mListPreference.isVisible()).isFalse();
+ }
+
+ @Test
+ public void onSubscriptionsChanged_goFromOneSubscriptionToTwo_prefAppears() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mListPreference.isVisible()).isFalse();
+
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ mController.onSubscriptionsChanged();
+
+ assertThat(mController.isAvailable()).isTrue();
+ assertThat(mListPreference.isVisible()).isTrue();
+ }
+
+ @Test
+ public void onSubscriptionsChanged_goFromTwoToThreeSubscriptions_listGetsUpdated() {
+ final SubscriptionInfo sub1 = createMockSub(111, "sub1");
+ final SubscriptionInfo sub2 = createMockSub(222, "sub2");
+ final SubscriptionInfo sub3 = createMockSub(333, "sub3");
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
+
+ mController.displayPreference(mScreen);
+ assertThat(mListPreference.getEntries().length).isEqualTo(3);
+
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
+ mController.onSubscriptionsChanged();
+
+ assertThat(mController.isAvailable()).isTrue();
+ assertThat(mListPreference.isVisible()).isTrue();
+ final CharSequence[] entries = mListPreference.getEntries();
+ final CharSequence[] entryValues = mListPreference.getEntryValues();
+ assertThat(entries.length).isEqualTo(4);
+ assertThat(entries[0].toString()).isEqualTo("sub1");
+ assertThat(entries[1].toString()).isEqualTo("sub2");
+ assertThat(entries[2].toString()).isEqualTo("sub3");
+ assertThat(entries[3].toString()).isEqualTo(
+ mContext.getString(R.string.calls_and_sms_ask_every_time));
+ assertThat(entryValues[0].toString()).isEqualTo("111");
+ assertThat(entryValues[1].toString()).isEqualTo("222");
+ assertThat(entryValues[2].toString()).isEqualTo("333");
+ assertThat(entryValues[3].toString()).isEqualTo(
+ Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+
+ private SubscriptionInfo createMockSub(int id, String displayName) {
+ final SubscriptionInfo sub = mock(SubscriptionInfo.class);
+ when(sub.getSubscriptionId()).thenReturn(id);
+ when(sub.getDisplayName()).thenReturn(displayName);
+ return sub;
+ }
+
+ private class TestDefaultSubscriptionController extends DefaultSubscriptionController {
+
+ public TestDefaultSubscriptionController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ protected SubscriptionInfo getDefaultSubscriptionInfo() {
+ return null;
+ }
+
+ @Override
+ protected int getDefaultSubscriptionId() {
+ return 0;
+ }
+
+ @Override
+ protected void setDefaultSubscription(int subscriptionId) {
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
index 0240bd834f8..55a4224bcbb 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
@@ -85,7 +85,13 @@ public class MobileNetworkSettingsTest {
}
@Test
- public void onAttach_noCrash() {
+ public void onAttach_noV2Flag_noCrash() {
+ mFragment.onAttach(mContext);
+ }
+
+ @Test
+ public void onAttach_v2Flag_noCrash() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
mFragment.onAttach(mContext);
}
diff --git a/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java b/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java
new file mode 100644
index 00000000000..bf6662dc946
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java
@@ -0,0 +1,40 @@
+package com.android.settings.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class NfcPanelTest {
+
+ private NfcPanel mPanel;
+
+ @Before
+ public void setUp() {
+ mPanel = NfcPanel.create(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getSlices_containsNecessarySlices() {
+ final List uris = mPanel.getSlices();
+
+ assertThat(uris).containsExactly(
+ CustomSliceRegistry.NFC_SLICE_URI);
+ }
+
+ @Test
+ public void getSeeMoreIntent_notNull() {
+ assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
index cbc5765ccc5..2b7bdeb6948 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
@@ -16,15 +16,22 @@
package com.android.settings.password;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.content.ComponentName;
import com.android.settings.R;
@@ -58,11 +65,7 @@ public class ChooseLockGenericControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new ChooseLockGenericController(
- application,
- 0 /* userId */,
- mDevicePolicyManager,
- mManagedLockPasswordProvider);
+ mController = createController(PASSWORD_COMPLEXITY_NONE);
SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
}
@@ -225,4 +228,44 @@ public class ChooseLockGenericControllerTest {
assertThat(upgradedQuality).named("upgradedQuality")
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
}
+
+ @Test
+ public void upgradeQuality_complexityHigh_minQualityNumericComplex() {
+ when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt()))
+ .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_HIGH);
+
+ assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+ .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
+ }
+
+ @Test
+ public void upgradeQuality_complexityMedium_minQualityNumericComplex() {
+ when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt()))
+ .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_MEDIUM);
+
+ assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+ .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
+ }
+
+ @Test
+ public void upgradeQuality_complexityLow_minQualitySomething() {
+ when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt()))
+ .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_LOW);
+
+ assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+ .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ }
+
+ private ChooseLockGenericController createController(
+ @PasswordComplexity int minPasswordComplexity) {
+ return new ChooseLockGenericController(
+ application,
+ 0 /* userId */,
+ minPasswordComplexity,
+ mDevicePolicyManager,
+ mManagedLockPasswordProvider);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
index e3242148ee4..a1db12ccf24 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
@@ -16,6 +16,15 @@
package com.android.settings.password;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.robolectric.RuntimeEnvironment.application;
@@ -27,8 +36,10 @@ import android.content.Intent;
import android.provider.Settings.Global;
import androidx.annotation.Nullable;
+import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.search.SearchFeatureProvider;
@@ -36,6 +47,7 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowStorageManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.widget.FooterPreference;
import org.junit.After;
import org.junit.Before;
@@ -112,6 +124,70 @@ public class ChooseLockGenericTest {
assertThat(shadowOf(mActivity).getNextStartedActivity()).isNull();
}
+ @Test
+ public void updatePreferencesOrFinish_footerPreferenceAddedHighComplexityText() {
+ ShadowStorageManager.setIsFileEncryptedNativeOrEmulated(false);
+ Intent intent = new Intent()
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name")
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ initActivity(intent);
+ CharSequence expectedTitle =
+ mActivity.getString(R.string.unlock_footer_high_complexity_requested, "app name");
+
+ mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
+ FooterPreference footer = mFragment.findPreference(FooterPreference.KEY_FOOTER);
+
+ assertThat(footer.getTitle()).isEqualTo(expectedTitle);
+ }
+
+ @Test
+ public void updatePreferencesOrFinish_footerPreferenceAddedMediumComplexityText() {
+ ShadowStorageManager.setIsFileEncryptedNativeOrEmulated(false);
+ Intent intent = new Intent()
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name")
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_MEDIUM);
+ initActivity(intent);
+ CharSequence expectedTitle =
+ mActivity.getString(R.string.unlock_footer_medium_complexity_requested, "app name");
+
+ mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
+ FooterPreference footer = mFragment.findPreference(FooterPreference.KEY_FOOTER);
+
+ assertThat(footer.getTitle()).isEqualTo(expectedTitle);
+ }
+
+ @Test
+ public void updatePreferencesOrFinish_footerPreferenceAddedLowComplexityText() {
+ ShadowStorageManager.setIsFileEncryptedNativeOrEmulated(false);
+ Intent intent = new Intent()
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name")
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_LOW);
+ initActivity(intent);
+ CharSequence expectedTitle =
+ mActivity.getString(R.string.unlock_footer_low_complexity_requested, "app name");
+
+ mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
+ FooterPreference footer = mFragment.findPreference(FooterPreference.KEY_FOOTER);
+
+ assertThat(footer.getTitle()).isEqualTo(expectedTitle);
+ }
+
+ @Test
+ public void updatePreferencesOrFinish_footerPreferenceAddedNoneComplexityText() {
+ ShadowStorageManager.setIsFileEncryptedNativeOrEmulated(false);
+ Intent intent = new Intent()
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name")
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
+ initActivity(intent);
+ CharSequence expectedTitle =
+ mActivity.getString(R.string.unlock_footer_none_complexity_requested, "app name");
+
+ mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
+ FooterPreference footer = mFragment.findPreference(FooterPreference.KEY_FOOTER);
+
+ assertThat(footer.getTitle()).isEqualTo(expectedTitle);
+ }
+
@Test
public void onActivityResult_requestcode0_shouldNotFinish() {
initActivity(null);
@@ -165,6 +241,48 @@ public class ChooseLockGenericTest {
assertThat(mActivity.isFinishing()).isTrue();
}
+ @Test
+ public void onPreferenceTreeClick_fingerprintPassesMinComplexityInfoOntoNextActivity() {
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD)
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH)
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name");
+ initActivity(intent);
+
+ Preference fingerprintPref = new Preference(application);
+ fingerprintPref.setKey("unlock_skip_fingerprint");
+ boolean result = mFragment.onPreferenceTreeClick(fingerprintPref);
+
+ assertThat(result).isTrue();
+ Intent actualIntent = shadowOf(mActivity).getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue();
+ assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE))
+ .isEqualTo(PASSWORD_COMPLEXITY_HIGH);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME))
+ .isEqualTo("app name");
+ }
+
+ @Test
+ public void onPreferenceTreeClick_facePassesMinComplexityInfoOntoNextActivity() {
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD)
+ .putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH)
+ .putExtra(EXTRA_KEY_CALLER_APP_NAME, "app name");
+ initActivity(intent);
+
+ Preference facePref = new Preference(application);
+ facePref.setKey("unlock_skip_face");
+ boolean result = mFragment.onPreferenceTreeClick(facePref);
+
+ assertThat(result).isTrue();
+ Intent actualIntent = shadowOf(mActivity).getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue();
+ assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE))
+ .isEqualTo(PASSWORD_COMPLEXITY_HIGH);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME))
+ .isEqualTo("app name");
+ }
+
private void initActivity(@Nullable Intent intent) {
if (intent == null) {
intent = new Intent();
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 367cb4c36b2..404d2057aa4 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -16,19 +16,37 @@
package com.android.settings.password;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static com.android.internal.widget.LockPatternUtils.PASSWORD_TYPE_KEY;
+import static com.android.settings.password.ChooseLockGeneric.CONFIRM_CREDENTIALS;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.robolectric.RuntimeEnvironment.application;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.content.Intent;
import android.os.UserHandle;
-import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment;
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
+import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupdesign.GlifLayout;
@@ -44,13 +62,21 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDrawable;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {SettingsShadowResources.class, ShadowUtils.class})
+@Config(shadows = {
+ SettingsShadowResources.class,
+ ShadowUtils.class,
+ ShadowDevicePolicyManager.class,
+})
public class ChooseLockPasswordTest {
+ private ShadowDevicePolicyManager mShadowDpm;
+
@Before
public void setUp() {
SettingsShadowResources.overrideResource(
com.android.internal.R.string.config_headlineFontFamily, "");
+ mShadowDpm = ShadowDevicePolicyManager.getShadow();
+ mShadowDpm.setPasswordMaximumLength(16);
}
@After
@@ -72,7 +98,7 @@ public class ChooseLockPasswordTest {
assertThat(intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.named("EXTRA_KEY_PASSWORD")
.isEqualTo("password");
- assertThat(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 0))
+ assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0))
.named("PASSWORD_TYPE_KEY")
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0))
@@ -84,7 +110,7 @@ public class ChooseLockPasswordTest {
public void intentBuilder_setChallenge_shouldAddExtras() {
Intent intent = new IntentBuilder(application)
.setChallenge(12345L)
- .setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC)
+ .setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC)
.setUserId(123)
.build();
@@ -94,14 +120,213 @@ public class ChooseLockPasswordTest {
assertThat(intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0L))
.named("EXTRA_KEY_CHALLENGE")
.isEqualTo(12345L);
- assertThat(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 0))
+ assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0))
.named("PASSWORD_TYPE_KEY")
- .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
+ .isEqualTo(PASSWORD_QUALITY_ALPHANUMERIC);
assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0))
.named("EXTRA_USER_ID")
.isEqualTo(123);
}
+ @Test
+ public void intentBuilder_setMinComplexityMedium_hasMinComplexityExtraMedium() {
+ Intent intent = new IntentBuilder(application)
+ .setRequestedMinComplexity(PASSWORD_COMPLEXITY_MEDIUM)
+ .build();
+
+ assertThat(intent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue();
+ assertThat(intent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE))
+ .isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
+ }
+
+ @Test
+ public void intentBuilder_setMinComplexityNotCalled() {
+ Intent intent = new IntentBuilder(application).build();
+
+ assertThat(intent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse();
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_noMinPasswordComplexity() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_ALPHABETIC);
+ mShadowDpm.setPasswordMinimumLength(10);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "",
+ "Must contain at least 1 letter",
+ "Must be at least 10 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_minPasswordComplexityStricter_pin() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_SOMETHING);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
+ /* userEnteredPassword= */ "",
+ "PIN must be at least 8 digits");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_minPasswordComplexityStricter_password() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_SOMETHING);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "",
+ "Must contain at least 1 letter",
+ "Must be at least 4 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_dpmRestrictionsStricter_password() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC);
+ mShadowDpm.setPasswordMinimumLength(9);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_LOW,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "",
+ "Must contain at least 1 letter",
+ "Must contain at least 1 numerical digit",
+ "Must be at least 9 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_dpmLengthLonger_pin() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC);
+ mShadowDpm.setPasswordMinimumLength(11);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM,
+ /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
+ /* userEnteredPassword= */ "",
+ "PIN must be at least 11 digits");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_dpmQualityComplex() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_COMPLEX);
+ mShadowDpm.setPasswordMinimumSymbols(2);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "",
+ "Must contain at least 2 special symbols",
+ "Must be at least 6 characters");
+ }
+
+ @Test
+ @Config(shadows = ShadowLockPatternUtils.class)
+ public void processAndValidatePasswordRequirements_numericComplexNoMinComplexity_pinRequested() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
+ /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
+ /* userEnteredPassword= */ "12345678",
+ "Ascending, descending, or repeated sequence of digits isn't allowed");
+ }
+
+ @Test
+ @Config(shadows = ShadowLockPatternUtils.class)
+ public void processAndValidatePasswordRequirements_numericComplexNoMinComplexity_passwordRequested() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "12345678",
+ "Ascending, descending, or repeated sequence of digits isn't allowed");
+ }
+
+ @Test
+ @Config(shadows = ShadowLockPatternUtils.class)
+ public void processAndValidatePasswordRequirements_numericComplexHighComplexity_pinRequested() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
+ /* userEnteredPassword= */ "12345678",
+ "Ascending, descending, or repeated sequence of digits isn't allowed");
+ }
+
+ @Test
+ @Config(shadows = ShadowLockPatternUtils.class)
+ public void processAndValidatePasswordRequirements_numericHighComplexity_pinRequested() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
+ /* userEnteredPassword= */ "12345678",
+ "Ascending, descending, or repeated sequence of digits isn't allowed");
+ }
+
+ @Test
+ @Config(shadows = ShadowLockPatternUtils.class)
+ public void processAndValidatePasswordRequirements_numericComplexLowComplexity_passwordRequested() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_LOW,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "12345678",
+ "Must contain at least 1 letter");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_empty() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "",
+ "Must contain at least 1 letter",
+ "Must be at least 6 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_numeric() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "1",
+ "Must contain at least 1 letter",
+ "Must be at least 6 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_alphabetic() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "b",
+ "Must be at least 6 characters");
+ }
+
+ @Test
+ public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_alphanumeric() {
+ mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED);
+
+ assertPasswordValidationResult(
+ /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
+ /* userEnteredPassword= */ "b1",
+ "Must be at least 6 characters");
+ }
+
@Test
public void assertThat_chooseLockIconChanged_WhenFingerprintExtraSet() {
ShadowDrawable drawable = setActivityAndGetIconDrawable(true);
@@ -132,4 +357,18 @@ public class ChooseLockPasswordTest {
ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity);
return Shadows.shadowOf(((GlifLayout) fragment.getView()).getIcon());
}
+
+ private void assertPasswordValidationResult(@PasswordComplexity int minComplexity,
+ int passwordType, String userEnteredPassword, String... expectedValidationResult) {
+ Intent intent = new Intent();
+ intent.putExtra(CONFIRM_CREDENTIALS, false);
+ intent.putExtra(PASSWORD_TYPE_KEY, passwordType);
+ intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity);
+ ChooseLockPassword activity = buildChooseLockPasswordActivity(intent);
+ ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(activity);
+ int validateResult = fragment.validatePassword(userEnteredPassword);
+ String[] messages = fragment.convertErrorCodeToMessages(validateResult);
+
+ assertThat(messages).asList().containsExactly((Object[]) expectedValidationResult);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java b/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java
new file mode 100644
index 00000000000..845d346da8f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.password;
+
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import static com.android.settings.password.PasswordUtils.getCallingAppLabel;
+import static com.android.settings.password.PasswordUtils.isCallingAppPermitted;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.settings.testutils.shadow.ShadowActivityManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowActivityManager.class})
+public class PasswordUtilsTest {
+
+ private static final String PACKAGE_NAME = "com.android.app";
+ private static final String PERMISSION = "com.testing.permission";
+ private static final int UID = 1234;
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mApplicationInfo;
+ @Mock
+ private IActivityManager mActivityService;
+ @Mock
+ private IBinder mActivityToken;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ ShadowActivityManager.setService(mActivityService);
+ }
+
+ @Test
+ public void getCallingAppLabel_activityServiceThrowsRemoteException_returnsNull()
+ throws Exception {
+ when(mActivityService.getLaunchedFromPackage(mActivityToken))
+ .thenThrow(new RemoteException());
+
+ assertThat(getCallingAppLabel(mContext, mActivityToken)).isNull();
+ }
+
+ @Test
+ public void getCallingAppLabel_activityServiceReturnsSettingsApp_returnsNull()
+ throws Exception {
+ when(mActivityService.getLaunchedFromPackage(mActivityToken))
+ .thenReturn("com.android.settings");
+
+ assertThat(getCallingAppLabel(mContext, mActivityToken)).isNull();
+ }
+
+ @Test
+ public void getCallingAppLabel_packageManagerThrowsNameNotFound_returnsNull() throws Exception {
+ when(mActivityService.getLaunchedFromPackage(mActivityToken))
+ .thenReturn(PACKAGE_NAME);
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenThrow(new NameNotFoundException());
+
+ assertThat(getCallingAppLabel(mContext, mActivityToken)).isNull();
+ }
+
+ @Test
+ public void getCallingAppLabel_returnsLabel() throws Exception {
+ when(mActivityService.getLaunchedFromPackage(mActivityToken))
+ .thenReturn(PACKAGE_NAME);
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(mApplicationInfo);
+ when(mApplicationInfo.loadLabel(mPackageManager)).thenReturn("label");
+
+ assertThat(getCallingAppLabel(mContext, mActivityToken)).isEqualTo("label");
+ }
+
+ @Test
+ public void isCallingAppPermitted_permissionGranted_returnsTrue() throws Exception {
+ when(mActivityService.getLaunchedFromUid(mActivityToken)).thenReturn(UID);
+ when(mContext.checkPermission(PERMISSION, -1, UID)).thenReturn(PERMISSION_GRANTED);
+
+ assertThat(isCallingAppPermitted(mContext, mActivityToken, PERMISSION)).isTrue();
+ }
+
+ @Test
+ public void isCallingAppPermitted_permissionDenied_returnsFalse() throws Exception {
+ when(mActivityService.getLaunchedFromUid(mActivityToken)).thenReturn(UID);
+ when(mContext.checkPermission(PERMISSION, -1, UID)).thenReturn(PERMISSION_DENIED);
+
+ assertThat(isCallingAppPermitted(mContext, mActivityToken, PERMISSION)).isFalse();
+ }
+
+ @Test
+ public void isCallingAppPermitted_throwsRemoteException_returnsFalse() throws Exception {
+ when(mActivityService.getLaunchedFromUid(mActivityToken)).thenThrow(new RemoteException());
+
+ assertThat(isCallingAppPermitted(mContext, mActivityToken, PERMISSION)).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
index 99738e75c33..d1b2b74b3c3 100644
--- a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
@@ -16,6 +16,16 @@
package com.android.settings.password;
+import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.ComponentName;
@@ -23,6 +33,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
+import com.android.settings.testutils.shadow.ShadowPasswordUtils;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -31,11 +43,14 @@ import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
@RunWith(RobolectricTestRunner.class)
public class SetNewPasswordActivityTest {
+ private static final String APP_LABEL = "label";
+
private int mProvisioned;
@Before
@@ -48,6 +63,7 @@ public class SetNewPasswordActivityTest {
public void tearDown() {
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, mProvisioned);
+ ShadowPasswordUtils.reset();
}
@Test
@@ -77,4 +93,106 @@ public class SetNewPasswordActivityTest {
assertThat(intent.getComponent())
.isEqualTo(new ComponentName(activity, SetupChooseLockGeneric.class));
}
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void testLaunchChooseLock_setNewPasswordExtraWithoutPermission() {
+ ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD);
+ intent.putExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ SetNewPasswordActivity activity =
+ Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ assertThat(shadowActivity.getNextStartedActivityForResult()).isNull();
+ }
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void testLaunchChooseLock_setNewPasswordExtraWithPermission() {
+ ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
+ ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD);
+ intent.putExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ SetNewPasswordActivity activity =
+ Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PASSWORD);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue();
+ assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE))
+ .isEqualTo(PASSWORD_COMPLEXITY_HIGH);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL);
+ }
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void testLaunchChooseLock_setNewPasswordExtraInvalidValue() {
+ ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
+ ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD);
+ intent.putExtra(EXTRA_PASSWORD_COMPLEXITY, -1);
+ SetNewPasswordActivity activity =
+ Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PASSWORD);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse();
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL);
+ }
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void testLaunchChooseLock_setNewPasswordExtraNoneComplexity() {
+ ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
+ ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+
+ Intent intent = new Intent(ACTION_SET_NEW_PASSWORD);
+ intent.putExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
+ SetNewPasswordActivity activity =
+ Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PASSWORD);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse();
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL);
+ }
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void testLaunchChooseLock_setNewParentProfilePasswordExtraWithPermission() {
+ ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
+ ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+
+ Intent intent = new Intent(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD);
+ intent.putExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ SetNewPasswordActivity activity =
+ Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent;
+ assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD);
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse();
+ assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue();
+ assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java
new file mode 100644
index 00000000000..63bdc381926
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.password;
+
+import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Intent;
+
+import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
+import com.android.settings.testutils.shadow.ShadowPasswordUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settings.testutils.shadow.ShadowUtils;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+ ShadowUserManager.class,
+ ShadowUtils.class,
+ ShadowLockPatternUtils.class,
+})
+public class SetupChooseLockGenericTest {
+
+ @After
+ public void tearDown() {
+ ShadowPasswordUtils.reset();
+ }
+
+ @Test
+ public void setupChooseLockGenericPasswordComplexityExtraWithoutPermission() {
+ Intent intent = new Intent("com.android.settings.SETUP_LOCK_SCREEN");
+ intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ SetupChooseLockGeneric activity =
+ Robolectric.buildActivity(SetupChooseLockGeneric.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ assertThat(shadowActivity.isFinishing()).isTrue();
+ }
+
+ @Test
+ @Config(shadows = {ShadowPasswordUtils.class})
+ public void setupChooseLockGenericPasswordComplexityExtraWithPermission() {
+ ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+
+ Intent intent = new Intent("com.android.settings.SETUP_LOCK_SCREEN");
+ intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
+ SetupChooseLockGeneric activity =
+ Robolectric.buildActivity(SetupChooseLockGeneric.class, intent).create().get();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ assertThat(shadowActivity.isFinishing()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
index 946ab69b486..e0c6dedc83f 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -38,7 +38,7 @@ import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.widget.ScrollToParentEditText;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
@@ -142,7 +142,7 @@ public class SetupChooseLockPasswordTest {
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton).isNotNull();
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
@@ -165,7 +165,7 @@ public class SetupChooseLockPasswordTest {
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton.isEnabled()).isTrue();
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.GONE);
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index e45869f17db..430c535428d 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -41,7 +41,7 @@ import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.Before;
import org.junit.Test;
@@ -148,7 +148,7 @@ public class SetupChooseLockPatternTest {
public void skipButton_shouldBeVisible_duringNonFingerprintFlow() {
PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton).isNotNull();
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
@@ -163,7 +163,7 @@ public class SetupChooseLockPatternTest {
PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(skipOrClearButton.isEnabled()).isTrue();
@@ -177,7 +177,7 @@ public class SetupChooseLockPatternTest {
PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton.isEnabled()).isTrue();
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(skipOrClearButton.getText())
diff --git a/tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java b/tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java
deleted file mode 100644
index 49a4e92ae43..00000000000
--- a/tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 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.security;
-
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.DialogInterface;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.androidx.fragment.FragmentController;
-
-@RunWith(RobolectricTestRunner.class)
-public class ConfigureKeyGuardDialogTest {
-
- @Test
- public void displayDialog_clickPositiveButton_launchSetNewPassword() {
- final FragmentController fragmentController =
- FragmentController.of(new ConfigureKeyGuardDialog());
- final ConfigureKeyGuardDialog fragment = spy(fragmentController.get());
- doNothing().when(fragment).startPasswordSetup();
- fragmentController.create().start().resume();
- fragment.onClick(null /* dialog */, DialogInterface.BUTTON_POSITIVE);
- fragment.onDismiss(null /* dialog */);
-
- verify(fragment).startPasswordSetup();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivityManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivityManager.java
index 38d658c3544..76bdaefa18e 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivityManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivityManager.java
@@ -17,6 +17,7 @@
package com.android.settings.testutils.shadow;
import android.app.ActivityManager;
+import android.app.IActivityManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -24,6 +25,7 @@ import org.robolectric.annotation.Implements;
@Implements(ActivityManager.class)
public class ShadowActivityManager {
private static int sCurrentUserId = 0;
+ private static IActivityManager sService = null;
@Implementation
protected static int getCurrentUser() {
@@ -33,4 +35,13 @@ public class ShadowActivityManager {
public static void setCurrentUser(int userId) {
sCurrentUserId = userId;
}
+
+ @Implementation
+ public static IActivityManager getService() {
+ return sService;
+ }
+
+ public static void setService(IActivityManager service) {
+ sService = service;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java
index 6d2dbef467c..ca759164b99 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java
@@ -1,5 +1,7 @@
package com.android.settings.testutils.shadow;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -23,6 +25,10 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
private boolean mIsAdminActiveAsUser = false;
private ComponentName mDeviceOwnerComponentName;
private int mDeviceOwnerUserId = -1;
+ private int mPasswordMinQuality = PASSWORD_QUALITY_UNSPECIFIED;
+ private int mPasswordMaxLength = 16;
+ private int mPasswordMinLength = 0;
+ private int mPasswordMinSymbols = 0;
public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) {
mSupportMessagesMap.put(Objects.hash(admin, userHandle), message);
@@ -70,6 +76,42 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
mDeviceOwnerComponentName = admin;
}
+ @Implementation
+ public int getPasswordQuality(ComponentName admin, int userHandle) {
+ return mPasswordMinQuality;
+ }
+
+ public void setPasswordQuality(int quality) {
+ mPasswordMinQuality = quality;
+ }
+
+ @Implementation
+ public int getPasswordMinimumLength(ComponentName admin, int userHandle) {
+ return mPasswordMinLength;
+ }
+
+ public void setPasswordMinimumLength(int length) {
+ mPasswordMinLength = length;
+ }
+
+ @Implementation
+ public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) {
+ return mPasswordMinSymbols;
+ }
+
+ public void setPasswordMinimumSymbols(int numOfSymbols) {
+ mPasswordMinSymbols = numOfSymbols;
+ }
+
+ @Implementation
+ public int getPasswordMaximumLength(int quality) {
+ return mPasswordMaxLength;
+ }
+
+ public void setPasswordMaximumLength(int length) {
+ mPasswordMaxLength = length;
+ }
+
public static ShadowDevicePolicyManager getShadow() {
return (ShadowDevicePolicyManager) Shadow.extract(
RuntimeEnvironment.application.getSystemService(DevicePolicyManager.class));
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
index 663ab91e580..7ce098d9ea8 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
@@ -59,4 +59,14 @@ public class ShadowLockPatternUtils {
public static void setDeviceEncryptionEnabled(boolean deviceEncryptionEnabled) {
sDeviceEncryptionEnabled = deviceEncryptionEnabled;
}
+
+ @Implementation
+ protected byte[] getPasswordHistoryHashFactor(String currentPassword, int userId) {
+ return null;
+ }
+
+ @Implementation
+ protected boolean checkPasswordHistory(String passwordToCheck, byte[] hashFactor, int userId) {
+ return false;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java
new file mode 100644
index 00000000000..6a5c4ae7c57
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.testutils.shadow;
+
+import android.content.Context;
+import android.os.IBinder;
+
+import com.android.settings.password.PasswordUtils;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+@Implements(PasswordUtils.class)
+public class ShadowPasswordUtils {
+
+ private static String sCallingAppLabel;
+ private static Set sGrantedPermissions;
+
+ public static void reset() {
+ sCallingAppLabel = null;
+ sGrantedPermissions = null;
+ }
+
+ @Implementation
+ protected static boolean isCallingAppPermitted(Context context, IBinder activityToken,
+ String permission) {
+ if (sGrantedPermissions == null) {
+ return false;
+ }
+ return sGrantedPermissions.contains(permission);
+ }
+
+ public static void addGrantedPermission(String... permissions) {
+ if (sGrantedPermissions == null) {
+ sGrantedPermissions = new HashSet<>();
+ }
+ sGrantedPermissions.addAll(Arrays.asList(permissions));
+ }
+
+ @Implementation
+ protected static String getCallingAppLabel(Context context, IBinder activityToken) {
+ return sCallingAppLabel;
+ }
+
+ public static void setCallingAppLabel(String label) {
+ sCallingAppLabel = label;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index d84d665b7c2..0286d07d074 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -27,16 +27,19 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle;
import android.widget.Button;
+import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
+import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.wifi.AccessPoint;
@@ -63,6 +66,7 @@ public class NetworkRequestDialogFragmentTest {
private static final String KEY_SSID = "key_ssid";
private static final String KEY_SECURITY = "key_security";
+ private static final String TEST_APP_NAME = "TestAppName";
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
@@ -71,7 +75,9 @@ public class NetworkRequestDialogFragmentTest {
@Before
public void setUp() {
- mActivity = Robolectric.setupActivity(FragmentActivity.class);
+ mActivity = Robolectric.buildActivity(FragmentActivity.class,
+ new Intent().putExtra(NetworkRequestDialogFragment.EXTRA_APP_NAME,
+ TEST_APP_NAME)).setup().get();
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
mContext = spy(RuntimeEnvironment.application);
@@ -87,6 +93,17 @@ public class NetworkRequestDialogFragmentTest {
assertThat(alertDialog.isShowing()).isTrue();
}
+ @Test
+ public void display_shouldShowTitleWithAppName() {
+ networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), /* tag */ null);
+ final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+
+ final String targetTitle = mContext.getString(
+ R.string.network_connection_request_dialog_title, TEST_APP_NAME);
+ final TextView view = alertDialog.findViewById(R.id.network_request_title_text);
+ assertThat(view.getText()).isEqualTo(targetTitle);
+ }
+
@Test
public void clickPositiveButton_shouldCloseTheDialog() {
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index 7ebb18e8004..fd25f7d9bb8 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.ServiceSpecificException;
import android.security.KeyStore;
@@ -39,6 +40,7 @@ import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.wifi.details.WifiPrivacyPreferenceController;
import com.android.settingslib.wifi.AccessPoint;
import org.junit.Before;
@@ -386,4 +388,61 @@ public class WifiConfigControllerTest {
@Override
KeyStore getKeyStore() { return mKeyStore; }
}
+
+ @Test
+ public void loadMacRandomizedValue_shouldPersistentAsDefault() {
+ final Spinner privacySetting = mView.findViewById(R.id.privacy_settings);
+ final int prefPersist =
+ WifiPrivacyPreferenceController.translateMacRandomizedValueToPrefValue(
+ WifiConfiguration.RANDOMIZATION_PERSISTENT);
+
+ assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(prefPersist);
+ }
+
+ @Test
+ public void loadSavedMacRandomizedPersistentValue_shouldCorrectMacValue() {
+ checkSavedMacRandomizedValue(WifiConfiguration.RANDOMIZATION_PERSISTENT);
+ }
+
+ @Test
+ public void loadSavedMacRandomizedNoneValue_shouldCorrectMacValue() {
+ checkSavedMacRandomizedValue(WifiConfiguration.RANDOMIZATION_NONE);
+ }
+
+ private void checkSavedMacRandomizedValue(int macRandomizedValue) {
+ when(mAccessPoint.isSaved()).thenReturn(true);
+ final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class);
+ when(mAccessPoint.getConfig()).thenReturn(mockWifiConfig);
+ mockWifiConfig.macRandomizationSetting = macRandomizedValue;
+ mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint,
+ WifiConfigUiBase.MODE_CONNECT);
+
+ final Spinner privacySetting = mView.findViewById(R.id.privacy_settings);
+ final int expectedPrefValue =
+ WifiPrivacyPreferenceController.translateMacRandomizedValueToPrefValue(
+ macRandomizedValue);
+
+ assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(expectedPrefValue);
+ }
+
+ @Test
+ public void saveMacRandomizedValue_noChanged_shouldPersistentAsDefault() {
+ WifiConfiguration config = mController.getConfig();
+ assertThat(config.macRandomizationSetting).isEqualTo(
+ WifiConfiguration.RANDOMIZATION_PERSISTENT);
+ }
+
+ @Test
+ public void saveMacRandomizedValue_ChangedToNone_shouldGetNone() {
+ final Spinner privacySetting = mView.findViewById(R.id.privacy_settings);
+ final int prefMacNone =
+ WifiPrivacyPreferenceController.translateMacRandomizedValueToPrefValue(
+ WifiConfiguration.RANDOMIZATION_NONE);
+ privacySetting.setSelection(prefMacNone);
+
+ WifiConfiguration config = mController.getConfig();
+ assertThat(config.macRandomizationSetting).isEqualTo(WifiConfiguration.RANDOMIZATION_NONE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index ae352cc55ce..dd99e5518a1 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -139,4 +139,11 @@ public class WifiSliceTest {
verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
}
+
+ @Test
+ public void onConnectedChanged_shouldNotifyChange() {
+ mWifiScanWorker.onConnectedChanged();
+
+ verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
+ }
}
diff --git a/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java b/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
index 3b4abfe64cb..503a78c6bb8 100644
--- a/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
+++ b/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
@@ -36,7 +36,7 @@ import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
@@ -70,7 +70,7 @@ public class EncryptionInterstitialTest {
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getPrimaryButtonView().performClick();
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
@@ -85,7 +85,7 @@ public class EncryptionInterstitialTest {
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().performClick();
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
index 0a46403e1c2..589680d1a13 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
@@ -37,7 +37,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.Rule;
import org.junit.Test;
@@ -62,7 +62,7 @@ public class FingerprintEnrollFinishTest {
PartnerCustomizationLayout layout =
mActivityRule.getActivity().findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getPrimaryButtonView().performClick();
intended(hasComponent(enrollingComponent));
assertFalse(mActivityRule.getActivity().isFinishing());
@@ -79,7 +79,7 @@ public class FingerprintEnrollFinishTest {
PartnerCustomizationLayout layout =
mActivityRule.getActivity().findViewById(R.id.setup_wizard_layout);
- layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
+ layout.getMixin(FooterBarMixin.class).getPrimaryButtonView().performClick();
intended(hasComponent(enrollingComponent));
assertTrue(mActivityRule.getActivity().isFinishing());
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
index 5078cc2501f..454de3d3e6a 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -33,7 +33,7 @@ import android.widget.TextView;
import com.android.settings.R;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -84,7 +84,7 @@ public class FingerprintEnrollIntroductionTest
assertNotNull(errorTextView.getText().toString());
PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
- final Button nextButton = layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView();
+ final Button nextButton = layout.getMixin(FooterBarMixin.class).getPrimaryButtonView();
assertEquals(View.GONE, nextButton.getVisibility());
}
diff --git a/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
index 269be26fac3..e12390cfbb3 100644
--- a/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -43,7 +43,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.Before;
import org.junit.Test;
@@ -67,7 +67,7 @@ public class ChooseLockPasswordTest {
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
assertThat(
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getVisibility())
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getVisibility())
.isEqualTo(View.GONE);
}
@@ -79,7 +79,7 @@ public class ChooseLockPasswordTest {
onView(withId(R.id.password_entry)).perform(ViewActions.typeText("1234"))
.perform(pressKey(KeyEvent.KEYCODE_ENTER));
assertThat(
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getVisibility())
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getVisibility())
.isEqualTo(View.GONE);
}
@@ -92,10 +92,10 @@ public class ChooseLockPasswordTest {
.perform(pressKey(KeyEvent.KEYCODE_ENTER))
.perform(ViewActions.typeText("1"));
// clear should be present if text field contains content
- assertThat(layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getText())
+ assertThat(layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getText())
.isEqualTo(mContext.getString(R.string.lockpassword_clear_label));
assertThat(
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getVisibility())
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getVisibility())
.isEqualTo(View.VISIBLE);
}
}
diff --git a/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java b/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
index 67c5ccee981..cc0253fda08 100644
--- a/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
+++ b/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
@@ -45,7 +45,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import com.google.android.setupcompat.PartnerCustomizationLayout;
-import com.google.android.setupcompat.template.ButtonFooterMixin;
+import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.Before;
import org.junit.Rule;
@@ -75,7 +75,7 @@ public class SetupChooseLockPasswordAppTest {
SetupChooseLockPassword activity = mActivityTestRule.launchActivity(null);
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
final Button skipOrClearButton =
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
assertThat(skipOrClearButton.getText()).isEqualTo(mContext.getString(R.string.skip_label));
assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
@@ -87,7 +87,7 @@ public class SetupChooseLockPasswordAppTest {
public void clearIsNotShown_when_activityLaunchedInitially() {
SetupChooseLockPassword activity = mActivityTestRule.launchActivity(null);
PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
- assertThat(layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getText())
+ assertThat(layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getText())
.isEqualTo(mContext.getString(R.string.lockpassword_clear_label));
}
@@ -98,7 +98,7 @@ public class SetupChooseLockPasswordAppTest {
onView(withId(R.id.password_entry)).perform(ViewActions.typeText("1234"))
.perform(pressKey(KeyEvent.KEYCODE_ENTER));
assertThat(
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getVisibility())
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getVisibility())
.isEqualTo(View.GONE);
}
@@ -114,7 +114,7 @@ public class SetupChooseLockPasswordAppTest {
.perform(ViewActions.typeText("1"));
// clear should be present if text field contains content
assertThat(
- layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().getVisibility())
+ layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().getVisibility())
.isEqualTo(View.VISIBLE);
}
}