Support remote device credentials validation in UI.
Test: m RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.password Test: Manual Bug: 258505917 Change-Id: Ifb9f15728eb8396b34c844d28f71a8e6e1aad837
This commit is contained in:
@@ -22,7 +22,9 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.StartLockscreenValidationRequest;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.os.UserManager;
|
||||
@@ -41,6 +43,8 @@ import com.android.settingslib.transition.SettingsTransitionHelper;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class ChooseLockSettingsHelper {
|
||||
|
||||
private static final String TAG = "ChooseLockSettingsHelper";
|
||||
@@ -132,6 +136,7 @@ public final class ChooseLockSettingsHelper {
|
||||
@Nullable private CharSequence mHeader;
|
||||
@Nullable private CharSequence mDescription;
|
||||
@Nullable private CharSequence mAlternateButton;
|
||||
@Nullable private CharSequence mCheckBoxLabel;
|
||||
private boolean mReturnCredentials;
|
||||
private boolean mExternal;
|
||||
private boolean mForegroundOnly;
|
||||
@@ -139,6 +144,9 @@ public final class ChooseLockSettingsHelper {
|
||||
private int mUserId;
|
||||
private boolean mAllowAnyUserId;
|
||||
private boolean mForceVerifyPath;
|
||||
private boolean mRemoteLockscreenValidation;
|
||||
@Nullable private StartLockscreenValidationRequest mStartLockscreenValidationRequest;
|
||||
@Nullable private ComponentName mRemoteLockscreenValidationServiceComponent;
|
||||
boolean mRequestGatekeeperPasswordHandle;
|
||||
|
||||
public Builder(@NonNull Activity activity) {
|
||||
@@ -191,6 +199,15 @@ public final class ChooseLockSettingsHelper {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param checkboxLabel text for the checkbox
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setCheckboxLabel(@Nullable CharSequence checkboxLabel) {
|
||||
mCheckBoxLabel = checkboxLabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param returnCredentials if true, puts the following credentials into intent for
|
||||
* onActivityResult with the following keys:
|
||||
@@ -253,6 +270,42 @@ public final class ChooseLockSettingsHelper {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isRemoteLockscreenValidation if true, remote device validation flow will be
|
||||
* started. {@link #setStartLockscreenValidationRequest} and
|
||||
* {@link #setRemoteLockscreenValidationServiceComponent}
|
||||
* must also be used to set the required data.
|
||||
*/
|
||||
@NonNull public Builder setRemoteLockscreenValidation(
|
||||
boolean isRemoteLockscreenValidation) {
|
||||
mRemoteLockscreenValidation = isRemoteLockscreenValidation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startLockScreenValidationRequest contains information necessary to perform remote
|
||||
* lockscreen validation such as the remote device's
|
||||
* lockscreen type, public key to be used for
|
||||
* encryption, and remaining attempts.
|
||||
*/
|
||||
@NonNull public Builder setStartLockscreenValidationRequest(
|
||||
StartLockscreenValidationRequest startLockScreenValidationRequest) {
|
||||
mStartLockscreenValidationRequest = startLockScreenValidationRequest;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param remoteLockscreenValidationServiceComponent the {@link ComponentName} of the
|
||||
* {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService}
|
||||
* that will be used to validate the lockscreen guess.
|
||||
*/
|
||||
@NonNull public Builder setRemoteLockscreenValidationServiceComponent(
|
||||
ComponentName remoteLockscreenValidationServiceComponent) {
|
||||
mRemoteLockscreenValidationServiceComponent =
|
||||
remoteLockscreenValidationServiceComponent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that LockSettingsService return a handle to the Gatekeeper Password (instead of
|
||||
* the Gatekeeper HAT). This allows us to use a single entry of the user's credential
|
||||
@@ -315,49 +368,41 @@ public final class ChooseLockSettingsHelper {
|
||||
return launchConfirmationActivity(mBuilder.mRequestCode, mBuilder.mTitle, mBuilder.mHeader,
|
||||
mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal,
|
||||
mBuilder.mForceVerifyPath, mBuilder.mUserId, mBuilder.mAlternateButton,
|
||||
mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly,
|
||||
mBuilder.mRequestGatekeeperPasswordHandle);
|
||||
mBuilder.mCheckBoxLabel, mBuilder.mRemoteLockscreenValidation,
|
||||
mBuilder.mStartLockscreenValidationRequest,
|
||||
mBuilder.mRemoteLockscreenValidationServiceComponent, mBuilder.mAllowAnyUserId,
|
||||
mBuilder.mForegroundOnly, mBuilder.mRequestGatekeeperPasswordHandle);
|
||||
}
|
||||
|
||||
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
boolean returnCredentials, boolean external, boolean forceVerifyPath,
|
||||
int userId, @Nullable CharSequence alternateButton, boolean allowAnyUser,
|
||||
boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
|
||||
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
|
||||
boolean launched = false;
|
||||
|
||||
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) {
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
launched = launchConfirmationActivity(request, title, header, description,
|
||||
returnCredentials || forceVerifyPath
|
||||
? ConfirmLockPattern.InternalActivity.class
|
||||
: ConfirmLockPattern.class, returnCredentials, external,
|
||||
forceVerifyPath, userId, alternateButton, allowAnyUser,
|
||||
foregroundOnly, requestGatekeeperPasswordHandle);
|
||||
break;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
||||
launched = launchConfirmationActivity(request, title, header, description,
|
||||
returnCredentials || forceVerifyPath
|
||||
? ConfirmLockPassword.InternalActivity.class
|
||||
: ConfirmLockPassword.class, returnCredentials, external,
|
||||
forceVerifyPath, userId, alternateButton, allowAnyUser,
|
||||
foregroundOnly, requestGatekeeperPasswordHandle);
|
||||
break;
|
||||
int userId, @Nullable CharSequence alternateButton,
|
||||
@Nullable CharSequence checkboxLabel, boolean remoteLockscreenValidation,
|
||||
@Nullable StartLockscreenValidationRequest startLockScreenValidationRequest,
|
||||
@Nullable ComponentName remoteLockscreenValidationServiceComponent,
|
||||
boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
|
||||
Optional<Class<?>> activityClass = determineAppropriateActivityClass(
|
||||
returnCredentials, forceVerifyPath, userId, startLockScreenValidationRequest);
|
||||
if (activityClass.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return launched;
|
||||
|
||||
return launchConfirmationActivity(request, title, header, description, activityClass.get(),
|
||||
returnCredentials, external, forceVerifyPath, userId, alternateButton,
|
||||
checkboxLabel, remoteLockscreenValidation, startLockScreenValidationRequest,
|
||||
remoteLockscreenValidationServiceComponent, allowAnyUser, foregroundOnly,
|
||||
requestGatekeeperPasswordHandle);
|
||||
}
|
||||
|
||||
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
|
||||
CharSequence message, Class<?> activityClass, boolean returnCredentials,
|
||||
boolean external, boolean forceVerifyPath, int userId,
|
||||
@Nullable CharSequence alternateButton, boolean allowAnyUser,
|
||||
boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
|
||||
@Nullable CharSequence alternateButton, @Nullable CharSequence checkbox,
|
||||
boolean remoteLockscreenValidation,
|
||||
@Nullable StartLockscreenValidationRequest startLockScreenValidationRequest,
|
||||
@Nullable ComponentName remoteLockscreenValidationServiceComponent,
|
||||
boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
|
||||
@@ -367,10 +412,16 @@ public final class ChooseLockSettingsHelper {
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, false);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.USE_FADE_ANIMATION, external);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION,
|
||||
remoteLockscreenValidation);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, forceVerifyPath);
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId);
|
||||
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
|
||||
intent.putExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL, checkbox);
|
||||
intent.putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
startLockScreenValidationRequest);
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE,
|
||||
@@ -405,6 +456,58 @@ public final class ChooseLockSettingsHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Optional<Integer> passwordQualityToLockTypes(int quality) {
|
||||
switch (quality) {
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
return Optional.of(KeyguardManager.PATTERN);
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
return Optional.of(KeyguardManager.PIN);
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
||||
return Optional.of(KeyguardManager.PASSWORD);
|
||||
}
|
||||
Log.e(TAG, String.format(
|
||||
"Cannot determine appropriate activity class for password quality %d",
|
||||
quality));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Class<?>> determineAppropriateActivityClass(boolean returnCredentials,
|
||||
boolean forceVerifyPath, int userId,
|
||||
@Nullable StartLockscreenValidationRequest startLockscreenValidationRequest) {
|
||||
int lockType;
|
||||
if (startLockscreenValidationRequest != null) {
|
||||
lockType = startLockscreenValidationRequest.getLockscreenUiType();
|
||||
} else {
|
||||
final int effectiveUserId = UserManager
|
||||
.get(mActivity).getCredentialOwnerProfile(userId);
|
||||
Optional<Integer> lockTypeOptional = passwordQualityToLockTypes(
|
||||
mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId));
|
||||
if (lockTypeOptional.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
lockType = lockTypeOptional.get();
|
||||
}
|
||||
|
||||
switch (lockType) {
|
||||
case KeyguardManager.PASSWORD:
|
||||
case KeyguardManager.PIN:
|
||||
return Optional.of(returnCredentials || forceVerifyPath
|
||||
? ConfirmLockPassword.InternalActivity.class
|
||||
: ConfirmLockPassword.class);
|
||||
case KeyguardManager.PATTERN:
|
||||
return Optional.of(returnCredentials || forceVerifyPath
|
||||
? ConfirmLockPattern.InternalActivity.class
|
||||
: ConfirmLockPattern.class);
|
||||
}
|
||||
Log.e(TAG, String.format("Cannot determine appropriate activity class for lock type %d",
|
||||
lockType));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private void copyOptionalExtras(Intent inIntent, Intent outIntent) {
|
||||
IntentSender intentSender = inIntent.getParcelableExtra(Intent.EXTRA_INTENT);
|
||||
if (intentSender != null) {
|
||||
|
Reference in New Issue
Block a user