Credential FRP: Add ACTION_CONFIRM_FRP_CREDENTIAL to ConfirmCredential

Bug: 36814845
Test: adb shell settings put global device_provisioned 0 && adb shell am start -a android.app.action.CONFIRM_FRP_CREDENTIAL
Change-Id: Id6ce6bc5ebd9c9e2a88790cc800678aff50e580f
This commit is contained in:
Adrian Roos
2017-03-30 18:02:25 -07:00
parent 6ac7b8c6be
commit 5a9a3cde62
7 changed files with 78 additions and 16 deletions

View File

@@ -1499,6 +1499,7 @@
android:theme="@android:style/Theme.NoDisplay"> android:theme="@android:style/Theme.NoDisplay">
<intent-filter android:priority="1"> <intent-filter android:priority="1">
<action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL" /> <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" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>

View File

@@ -1012,7 +1012,24 @@ public final class Utils extends com.android.settingslib.Utils {
return getCredentialOwnerUserId(context); return getCredentialOwnerUserId(context);
} }
int userId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId()); 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());
} }
/** /**

View File

@@ -19,10 +19,13 @@ package com.android.settings.password;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender; import android.content.IntentSender;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
@@ -202,6 +205,21 @@ public final class ChooseLockSettingsHelper {
@Nullable CharSequence header, @Nullable CharSequence description, @Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge, boolean returnCredentials, boolean external, boolean hasChallenge,
long challenge, int userId) { 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); final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
boolean launched = false; boolean launched = false;
@@ -211,7 +229,7 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge returnCredentials || hasChallenge
? ConfirmLockPattern.InternalActivity.class ? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, returnCredentials, external, : ConfirmLockPattern.class, returnCredentials, external,
hasChallenge, challenge, userId); hasChallenge, challenge, userId, alternateButton);
break; break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
@@ -223,7 +241,7 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge returnCredentials || hasChallenge
? ConfirmLockPassword.InternalActivity.class ? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, returnCredentials, external, : ConfirmLockPassword.class, returnCredentials, external,
hasChallenge, challenge, userId); hasChallenge, challenge, userId, alternateButton);
break; break;
} }
return launched; return launched;
@@ -232,7 +250,7 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header, private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean returnCredentials, CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge, boolean external, boolean hasChallenge, long challenge,
int userId) { int userId, @Nullable CharSequence alternateButton) {
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title); intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header); intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -247,6 +265,7 @@ public final class ChooseLockSettingsHelper {
// we should never have a drawer when confirming device credentials. // we should never have a drawer when confirming device credentials.
intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true); intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true);
intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName()); intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
if (external) { if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);

View File

@@ -66,6 +66,10 @@ public class ConfirmDeviceCredentialActivity extends Activity {
Intent intent = getIntent(); Intent intent = getIntent();
String title = intent.getStringExtra(KeyguardManager.EXTRA_TITLE); String title = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION); 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); int userId = Utils.getCredentialOwnerUserId(this);
if (isInternalActivity()) { if (isInternalActivity()) {
try { try {
@@ -86,7 +90,9 @@ public class ConfirmDeviceCredentialActivity extends Activity {
// If the target is a managed user and user key not unlocked yet, we will force unlock // 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 // tied profile so it will enable work mode and unlock managed profile, when personal
// challenge is unlocked. // challenge is unlocked.
if (isManagedProfile && isInternalActivity() if (frp) {
launched = helper.launchFrpConfirmationActivity(0, title, details, alternateButton);
} else if (isManagedProfile && isInternalActivity()
&& !lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { && !lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
// We set the challenge as 0L, so it will force to unlock managed profile when it // We set the challenge as 0L, so it will force to unlock managed profile when it
// unlocks primary profile screen lock, by calling verifyTiedProfileChallenge() // unlocks primary profile screen lock, by calling verifyTiedProfileChallenge()

View File

@@ -25,6 +25,7 @@ import android.app.Dialog;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.IActivityManager; import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager; import android.app.trust.TrustManager;
import android.content.Context; import android.content.Context;
@@ -40,6 +41,7 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserManager; import android.os.UserManager;
import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
@@ -86,15 +88,20 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
protected DevicePolicyManager mDevicePolicyManager; protected DevicePolicyManager mDevicePolicyManager;
protected TextView mErrorTextView; protected TextView mErrorTextView;
protected final Handler mHandler = new Handler(); protected final Handler mHandler = new Handler();
protected boolean mFrp;
private CharSequence mFrpAlternateButtonText;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mFrpAlternateButtonText = getActivity().getIntent().getCharSequenceExtra(
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
mReturnCredentials = getActivity().getIntent().getBooleanExtra( mReturnCredentials = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false); ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
// Only take this argument into account if it belongs to the current profile. // Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent(); Intent intent = getActivity().getIntent();
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras()); mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
mFrp = (mUserId == LockPatternUtils.USER_FRP);
mUserManager = UserManager.get(getActivity()); mUserManager = UserManager.get(getActivity());
mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId); mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
mLockPatternUtils = new LockPatternUtils(getActivity()); mLockPatternUtils = new LockPatternUtils(getActivity());
@@ -112,10 +119,18 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
(TextView) view.findViewById(R.id.errorText), this, mEffectiveUserId); (TextView) view.findViewById(R.id.errorText), this, mEffectiveUserId);
boolean showCancelButton = getActivity().getIntent().getBooleanExtra( boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
SHOW_CANCEL_BUTTON, false); 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() { mCancelButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (hasAlternateButton) {
getActivity().setResult(KeyguardManager.RESULT_ALTERNATE);
}
getActivity().finish(); getActivity().finish();
} }
}); });
@@ -139,15 +154,16 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
// credential. Otherwise, fingerprint can't unlock fbe/keystore through // credential. Otherwise, fingerprint can't unlock fbe/keystore through
// verifyTiedProfileChallenge. In such case, we also wanna show the user message that // verifyTiedProfileChallenge. In such case, we also wanna show the user message that
// fingerprint is disabled due to device restart. // fingerprint is disabled due to device restart.
protected boolean isFingerprintDisallowedByStrongAuth() { protected boolean isStrongAuthRequired() {
return !(mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId) return mFrp
&& mUserManager.isUserUnlocked(mUserId)); || !mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId)
|| !mUserManager.isUserUnlocked(mUserId);
} }
private boolean isFingerprintAllowed() { private boolean isFingerprintAllowed() {
return !mReturnCredentials return !mReturnCredentials
&& getActivity().getIntent().getBooleanExtra(ALLOW_FP_AUTHENTICATION, false) && getActivity().getIntent().getBooleanExtra(ALLOW_FP_AUTHENTICATION, false)
&& !isFingerprintDisallowedByStrongAuth() && !isStrongAuthRequired()
&& !isFingerprintDisabledByAdmin(); && !isFingerprintDisabledByAdmin();
} }

View File

@@ -16,7 +16,6 @@
package com.android.settings.password; package com.android.settings.password;
import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
@@ -45,7 +44,6 @@ import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.TextViewInputDisabler; import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settingslib.animation.AppearAnimationUtils; import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils; import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -197,7 +195,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
} }
private int getDefaultDetails() { private int getDefaultDetails() {
boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth(); boolean isStrongAuthRequired = isStrongAuthRequired();
boolean isProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId); boolean isProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId);
// Map boolean flags to an index by isStrongAuth << 2 + isProfile << 1 + isAlpha. // Map boolean flags to an index by isStrongAuth << 2 + isProfile << 1 + isAlpha.
int index = ((isStrongAuthRequired ? 1 : 0) << 2) + ((isProfile ? 1 : 0) << 1) int index = ((isStrongAuthRequired ? 1 : 0) << 2) + ((isProfile ? 1 : 0) << 1)

View File

@@ -38,7 +38,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView; import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell; import com.android.internal.widget.LockPatternView.Cell;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settingslib.animation.AppearAnimationCreator; import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils; import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils; import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -155,7 +154,13 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
// on first launch, if no lock pattern is set, then finish with // on first launch, if no lock pattern is set, then finish with
// success (don't want user to get stuck confirming something that // success (don't want user to get stuck confirming something that
// doesn't exist). // 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().setResult(Activity.RESULT_OK);
getActivity().finish(); getActivity().finish();
} }
@@ -238,7 +243,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
} }
private int getDefaultDetails() { private int getDefaultDetails() {
boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth(); boolean isStrongAuthRequired = isStrongAuthRequired();
if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) { if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) {
return isStrongAuthRequired return isStrongAuthRequired
? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern ? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern