android:theme="@android:style/Theme.NoDisplay">
<intent-filter android:priority="1">
<action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL" />
+ <action android:name="android.app.action.CONFIRM_FRP_CREDENTIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
return getCredentialOwnerUserId(context);
}
int userId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
- return enforceSameOwner(context, userId);
+ if (userId == LockPatternUtils.USER_FRP) {
+ return enforceSystemUser(context, userId);
+ } else {
+ return enforceSameOwner(context, userId);
+ }
+ }
+
+ /**
+ * Returns the given user id if the current user is the system user.
+ *
+ * @throws SecurityException if the current user is not the system user.
+ */
+ public static int enforceSystemUser(Context context, int userId) {
+ if (UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
+ return userId;
+ }
+ throw new SecurityException("Given user id " + userId + " must only be used from "
+ + "USER_SYSTEM, but current user is " + UserHandle.myUserId());
}
/**
import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
+import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.UserManager;
+import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge,
long challenge, int userId) {
+ return launchConfirmationActivity(request, title, header, description, returnCredentials,
+ external, hasChallenge, challenge, userId, null /* alternateButton */);
+ }
+
+ public boolean launchFrpConfirmationActivity(int request, @Nullable CharSequence header,
+ @Nullable CharSequence description, @Nullable CharSequence alternateButton) {
+ return launchConfirmationActivity(request, null /* title */, header, description,
+ false /* returnCredentials */, true /* external */, false /* hasChallenge */,
+ 0 /* challenge */, LockPatternUtils.USER_FRP, alternateButton);
+ }
+
+ private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
+ @Nullable CharSequence header, @Nullable CharSequence description,
+ boolean returnCredentials, boolean external, boolean hasChallenge,
+ long challenge, int userId, @Nullable CharSequence alternateButton) {
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
boolean launched = false;
returnCredentials || hasChallenge
? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, returnCredentials, external,
- hasChallenge, challenge, userId);
+ hasChallenge, challenge, userId, alternateButton);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
returnCredentials || hasChallenge
? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, returnCredentials, external,
- hasChallenge, challenge, userId);
+ hasChallenge, challenge, userId, alternateButton);
break;
}
return launched;
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge,
- int userId) {
+ int userId, @Nullable CharSequence alternateButton) {
final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
// we should never have a drawer when confirming device credentials.
intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
+ intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
Intent intent = getIntent();
String title = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
+ String alternateButton = intent.getStringExtra(
+ KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
+ boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
+
int userId = Utils.getCredentialOwnerUserId(this);
if (isInternalActivity()) {
try {
// If the target is a managed user and user key not unlocked yet, we will force unlock
// tied profile so it will enable work mode and unlock managed profile, when personal
// challenge is unlocked.
- if (isManagedProfile && isInternalActivity()
+ if (frp) {
+ launched = helper.launchFrpConfirmationActivity(0, title, details, alternateButton);
+ } else if (isManagedProfile && isInternalActivity()
&& !lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
// We set the challenge as 0L, so it will force to unlock managed profile when it
// unlocks primary profile screen lock, by calling verifyTiedProfileChallenge()
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.IActivityManager;
+import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager;
+import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
protected DevicePolicyManager mDevicePolicyManager;
protected TextView mErrorTextView;
protected final Handler mHandler = new Handler();
+ protected boolean mFrp;
+ private CharSequence mFrpAlternateButtonText;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mFrpAlternateButtonText = getActivity().getIntent().getCharSequenceExtra(
+ KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
mReturnCredentials = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
// Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent();
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
+ mFrp = (mUserId == LockPatternUtils.USER_FRP);
mUserManager = UserManager.get(getActivity());
mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
mLockPatternUtils = new LockPatternUtils(getActivity());
(TextView) view.findViewById(R.id.errorText), this, mEffectiveUserId);
boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
SHOW_CANCEL_BUTTON, false);
- mCancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
+ boolean hasAlternateButton = mFrp && !TextUtils.isEmpty(mFrpAlternateButtonText);
+ mCancelButton.setVisibility(showCancelButton || hasAlternateButton
+ ? View.VISIBLE : View.GONE);
+ if (hasAlternateButton) {
+ mCancelButton.setText(mFrpAlternateButtonText);
+ }
mCancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ if (hasAlternateButton) {
+ getActivity().setResult(KeyguardManager.RESULT_ALTERNATE);
+ }
getActivity().finish();
}
});
// credential. Otherwise, fingerprint can't unlock fbe/keystore through
// verifyTiedProfileChallenge. In such case, we also wanna show the user message that
// fingerprint is disabled due to device restart.
- protected boolean isFingerprintDisallowedByStrongAuth() {
- return !(mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId)
- && mUserManager.isUserUnlocked(mUserId));
+ protected boolean isStrongAuthRequired() {
+ return mFrp
+ || !mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId)
+ || !mUserManager.isUserUnlocked(mUserId);
}
private boolean isFingerprintAllowed() {
return !mReturnCredentials
&& getActivity().getIntent().getBooleanExtra(ALLOW_FP_AUTHENTICATION, false)
- && !isFingerprintDisallowedByStrongAuth()
+ && !isStrongAuthRequired()
&& !isFingerprintDisabledByAdmin();
}
package com.android.settings.password;
-import android.app.Activity;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.R;
-import com.android.settings.SettingsActivity;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
}
private int getDefaultDetails() {
- boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
+ boolean isStrongAuthRequired = isStrongAuthRequired();
boolean isProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId);
// Map boolean flags to an index by isStrongAuth << 2 + isProfile << 1 + isAlpha.
int index = ((isStrongAuthRequired ? 1 : 0) << 2) + ((isProfile ? 1 : 0) << 1)
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
import com.android.settings.R;
-import com.android.settings.SettingsActivity;
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
// on first launch, if no lock pattern is set, then finish with
// success (don't want user to get stuck confirming something that
// doesn't exist).
- if (!mLockPatternUtils.isLockPatternEnabled(mEffectiveUserId)) {
+ // Don't do this check for FRP though, because the pattern is not stored
+ // in a way that isLockPatternEnabled is aware of for that case.
+ // TODO(roosa): This block should no longer be needed since we removed the
+ // ability to disable the pattern in L. Remove this block after
+ // ensuring it's safe to do so. (Note that ConfirmLockPassword
+ // doesn't have this).
+ if (!mFrp && !mLockPatternUtils.isLockPatternEnabled(mEffectiveUserId)) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
}
}
private int getDefaultDetails() {
- boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
+ boolean isStrongAuthRequired = isStrongAuthRequired();
if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) {
return isStrongAuthRequired
? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern