OSDN Git Service

Credential FRP: Add ACTION_CONFIRM_FRP_CREDENTIAL to ConfirmCredential
authorAdrian Roos <roosa@google.com>
Fri, 31 Mar 2017 01:02:25 +0000 (18:02 -0700)
committerAdrian Roos <roosa@google.com>
Wed, 31 May 2017 01:25:18 +0000 (18:25 -0700)
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

AndroidManifest.xml
src/com/android/settings/Utils.java
src/com/android/settings/password/ChooseLockSettingsHelper.java
src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
src/com/android/settings/password/ConfirmLockPassword.java
src/com/android/settings/password/ConfirmLockPattern.java

index 0ee20a1..7dd42df 100644 (file)
             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>
index 9eeabe8..f0d5107 100644 (file)
@@ -1012,7 +1012,24 @@ public final class Utils extends com.android.settingslib.Utils {
             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());
     }
 
     /**
index 8c73355..95f5a54 100644 (file)
@@ -19,10 +19,13 @@ package com.android.settings.password;
 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;
@@ -202,6 +205,21 @@ public final class ChooseLockSettingsHelper {
             @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;
 
@@ -211,7 +229,7 @@ public final class ChooseLockSettingsHelper {
                         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:
@@ -223,7 +241,7 @@ public final class ChooseLockSettingsHelper {
                         returnCredentials || hasChallenge
                                 ? ConfirmLockPassword.InternalActivity.class
                                 : ConfirmLockPassword.class, returnCredentials, external,
-                                hasChallenge, challenge, userId);
+                                hasChallenge, challenge, userId, alternateButton);
                 break;
         }
         return launched;
@@ -232,7 +250,7 @@ public final class ChooseLockSettingsHelper {
     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);
@@ -247,6 +265,7 @@ public final class ChooseLockSettingsHelper {
         // 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);
index 38b38fc..65d72f1 100644 (file)
@@ -66,6 +66,10 @@ public class ConfirmDeviceCredentialActivity extends Activity {
         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 {
@@ -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
         // 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()
index 0c36dba..64f3a6f 100644 (file)
@@ -25,6 +25,7 @@ import android.app.Dialog;
 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;
@@ -40,6 +41,7 @@ import android.os.Bundle;
 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;
@@ -86,15 +88,20 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
     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());
@@ -112,10 +119,18 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
                 (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();
             }
         });
@@ -139,15 +154,16 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
     // 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();
     }
 
index a91f572..0acdcd8 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.settings.password;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
 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.TextViewInputDisabler;
 import com.android.settings.R;
-import com.android.settings.SettingsActivity;
 import com.android.settingslib.animation.AppearAnimationUtils;
 import com.android.settingslib.animation.DisappearAnimationUtils;
 
@@ -197,7 +195,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
         }
 
         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)
index c16b55a..2931596 100644 (file)
@@ -38,7 +38,6 @@ import com.android.internal.widget.LockPatternUtils;
 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;
@@ -155,7 +154,13 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
                 // 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();
                 }
@@ -238,7 +243,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
         }
 
         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