Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 127da9c7 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Fix ConfirmDeviceCredentials for work profiles

1) Fixed the theme for CDCA$InternalActivity to be transparent
2) CDCA only cares about biometrics, which are tied to userId
3) Moved shared methods to a util class

Fixes: 119296586

Test: Followed the steps in comment#1 of the bug linked above


Change-Id: Ie47fc7c3a53dfb7780087937e1ca83287cc52d71
parent f68130c7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1463,7 +1463,7 @@
            android:exported="false"
            android:permission="android.permission.MANAGE_USERS"
            android:resizeableActivity="false"
            android:theme="@android:style/Theme.NoDisplay">
            android:theme="@android:style/Theme.Translucent.NoTitleBar">
            <intent-filter android:priority="1">
                <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
                <category android:name="android.intent.category.DEFAULT" />
+9 −2
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ public class BiometricFragment extends InstrumentedFragment {
    private Executor mClientExecutor;
    private AuthenticationCallback mClientCallback;

    // Re-settable by the application.
    private int mUserId;

    // Created/Initialized once and retained
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private PromptInfo mPromptInfo;
@@ -96,6 +99,10 @@ public class BiometricFragment extends InstrumentedFragment {
        mClientCallback = callback;
    }

    public void setUser(int userId) {
        mUserId = userId;
    }

    public void cancel() {
        if (mCancellationSignal != null) {
            mCancellationSignal.cancel();
@@ -126,8 +133,8 @@ public class BiometricFragment extends InstrumentedFragment {
        mCancellationSignal = new CancellationSignal();

        // TODO: CC doesn't use crypto for now
        mBiometricPrompt.authenticate(mCancellationSignal, mClientExecutor,
                mAuthenticationCallback);
        mBiometricPrompt.authenticateUser(mCancellationSignal, mClientExecutor,
                mAuthenticationCallback, mUserId);
    }

    @Override
+23 −12
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ package com.android.settings.password;
import android.app.Activity;
import android.app.KeyguardManager;
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;
@@ -84,13 +84,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
    private DevicePolicyManager mDevicePolicyManager;
    private LockPatternUtils mLockPatternUtils;
    private UserManager mUserManager;
    private TrustManager mTrustManager;
    private ChooseLockSettingsHelper mChooseLockSettingsHelper;
    private Handler mHandler = new Handler(Looper.getMainLooper());

    private String mTitle;
    private String mDetails;
    private int mUserId;
    private int mEffectiveUserId;
    private int mCredentialMode;
    private boolean mGoingToBackground;

@@ -108,10 +108,16 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
                    showConfirmCredentials();
                }
            }

        }

        public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
            mTrustManager.setDeviceLockedForUser(mUserId, false);

            ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, mUserManager,
                    mUserId);
            ConfirmDeviceCredentialUtils.checkForPendingIntent(
                    ConfirmDeviceCredentialActivity.this);

            setResult(Activity.RESULT_OK);
            finish();
        }
@@ -124,6 +130,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
        mBiometricManager = getSystemService(BiometricManager.class);
        mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
        mUserManager = UserManager.get(this);
        mTrustManager = getSystemService(TrustManager.class);
        mLockPatternUtils = new LockPatternUtils(this);

        Intent intent = getIntent();
@@ -134,7 +141,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
        boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());

        mUserId = UserHandle.myUserId();
        mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
        final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
        if (isInternalActivity()) {
            try {
                mUserId = Utils.getUserIdFromBundle(this, intent.getExtras());
@@ -162,21 +169,23 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
        } else if (isManagedProfile && isInternalActivity()
                && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
            mCredentialMode = CREDENTIAL_MANAGED;
            if (isBiometricAllowed()) {
            if (isBiometricAllowed(effectiveUserId)) {
                showBiometricPrompt();
                launchedBiometric = true;
            } else {
                showConfirmCredentials();
                launchedCDC = true;
            }
        } else {
            mCredentialMode = CREDENTIAL_NORMAL;
            if (isBiometricAllowed()) {
            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();
                launchedBiometric = true;
            } else {
                showConfirmCredentials();
                launchedCDC = true;
            }
        }

@@ -217,19 +226,20 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
    // credential. Otherwise, biometric can't unlock fbe/keystore through
    // verifyTiedProfileChallenge. In such case, we also wanna show the user message that
    // biometric is disabled due to device restart.
    private boolean isStrongAuthRequired() {
        return !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId)
    private boolean isStrongAuthRequired(int effectiveUserId) {
        return !mLockPatternUtils.isBiometricAllowedForUser(effectiveUserId)
                || !mUserManager.isUserUnlocked(mUserId);
    }

    private boolean isBiometricDisabledByAdmin() {
    private boolean isBiometricDisabledByAdmin(int effectiveUserId) {
        final int disabledFeatures =
                mDevicePolicyManager.getKeyguardDisabledFeatures(null, mEffectiveUserId);
                mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
        return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0;
    }

    private boolean isBiometricAllowed() {
        return !isStrongAuthRequired() && !isBiometricDisabledByAdmin();
    private boolean isBiometricAllowed(int effectiveUserId) {
        return !isStrongAuthRequired(effectiveUserId)
                && !isBiometricDisabledByAdmin(effectiveUserId);
    }

    private void showBiometricPrompt() {
@@ -250,6 +260,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
            newFragment = true;
        }
        mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
        mBiometricFragment.setUser(mUserId);

        if (newFragment) {
            getSupportFragmentManager().beginTransaction()
+0 −38
Original line number Diff line number Diff line
@@ -18,17 +18,12 @@
package com.android.settings.password;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Dialog;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.UserInfo;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -36,7 +31,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager;
import android.text.TextUtils;
import android.view.View;
@@ -199,29 +193,6 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
    public void startEnterAnimation() {
    }

    protected void checkForPendingIntent() {
        int taskId = getActivity().getIntent().getIntExtra(Intent.EXTRA_TASK_ID, -1);
        if (taskId != -1) {
            try {
                IActivityManager activityManager = ActivityManager.getService();
                final ActivityOptions options = ActivityOptions.makeBasic();
                activityManager.startActivityFromRecents(taskId, options.toBundle());
                return;
            } catch (RemoteException e) {
                // Do nothing.
            }
        }
        IntentSender intentSender = getActivity().getIntent()
                .getParcelableExtra(Intent.EXTRA_INTENT);
        if (intentSender != null) {
            try {
                getActivity().startIntentSenderForResult(intentSender, -1, null, 0, 0, 0);
            } catch (IntentSender.SendIntentException e) {
                /* ignore */
            }
        }
    }

    private void setWorkChallengeBackground(View baseView, int userId) {
        View mainContent = getActivity().findViewById(com.android.settings.R.id.main_content);
        if (mainContent != null) {
@@ -246,15 +217,6 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
        }
    }

    protected void reportSuccessfulAttempt() {
        mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId);
        if (mUserManager.isManagedProfile(mEffectiveUserId)) {
            // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth
            // for work challenge only here.
            mLockPatternUtils.userPresent(mEffectiveUserId);
        }
    }

    protected void reportFailedAttempt() {
        updateErrorMessage(
                mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.content.Intent;
import android.content.IntentSender;
import android.os.RemoteException;
import android.os.UserManager;

import com.android.internal.widget.LockPatternUtils;

/** Class containing methods shared between CDCA and CDCBA */
public class ConfirmDeviceCredentialUtils {

    public static void checkForPendingIntent(Activity activity) {
        // See Change-Id I52c203735fa9b53fd2f7df971824747eeb930f36 for context
        int taskId = activity.getIntent().getIntExtra(Intent.EXTRA_TASK_ID, -1);
        if (taskId != -1) {
            try {
                IActivityManager activityManager = ActivityManager.getService();
                final ActivityOptions options = ActivityOptions.makeBasic();
                activityManager.startActivityFromRecents(taskId, options.toBundle());
                return;
            } catch (RemoteException e) {
                // Do nothing.
            }
        }
        IntentSender intentSender = activity.getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
        if (intentSender != null) {
            try {
                activity.startIntentSenderForResult(intentSender, -1, null, 0, 0, 0);
            } catch (IntentSender.SendIntentException e) {
                /* ignore */
            }
        }
    }

    public static void reportSuccessfulAttempt(LockPatternUtils utils, UserManager userManager,
            int userId) {
        utils.reportSuccessfulPasswordAttempt(userId);
        if (userManager.isManagedProfile(userId)) {
            // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth
            // for work challenge only here.
            utils.userPresent(userId);
        }
    }
}
Loading