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
This commit is contained in:
Kevin Chyn
2018-11-09 16:13:53 -08:00
parent f68130c7c7
commit 127da9c73c
7 changed files with 104 additions and 57 deletions

View File

@@ -1463,7 +1463,7 @@
android:exported="false" android:exported="false"
android:permission="android.permission.MANAGE_USERS" android:permission="android.permission.MANAGE_USERS"
android:resizeableActivity="false" android:resizeableActivity="false"
android:theme="@android:style/Theme.NoDisplay"> android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter android:priority="1"> <intent-filter android:priority="1">
<action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" /> <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />

View File

@@ -50,6 +50,9 @@ public class BiometricFragment extends InstrumentedFragment {
private Executor mClientExecutor; private Executor mClientExecutor;
private AuthenticationCallback mClientCallback; private AuthenticationCallback mClientCallback;
// Re-settable by the application.
private int mUserId;
// Created/Initialized once and retained // Created/Initialized once and retained
private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Handler mHandler = new Handler(Looper.getMainLooper());
private PromptInfo mPromptInfo; private PromptInfo mPromptInfo;
@@ -96,6 +99,10 @@ public class BiometricFragment extends InstrumentedFragment {
mClientCallback = callback; mClientCallback = callback;
} }
public void setUser(int userId) {
mUserId = userId;
}
public void cancel() { public void cancel() {
if (mCancellationSignal != null) { if (mCancellationSignal != null) {
mCancellationSignal.cancel(); mCancellationSignal.cancel();
@@ -126,8 +133,8 @@ public class BiometricFragment extends InstrumentedFragment {
mCancellationSignal = new CancellationSignal(); mCancellationSignal = new CancellationSignal();
// TODO: CC doesn't use crypto for now // TODO: CC doesn't use crypto for now
mBiometricPrompt.authenticate(mCancellationSignal, mClientExecutor, mBiometricPrompt.authenticateUser(mCancellationSignal, mClientExecutor,
mAuthenticationCallback); mAuthenticationCallback, mUserId);
} }
@Override @Override

View File

@@ -20,9 +20,9 @@ package com.android.settings.password;
import android.app.Activity; import android.app.Activity;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback; import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
@@ -84,13 +84,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private DevicePolicyManager mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private UserManager mUserManager; private UserManager mUserManager;
private TrustManager mTrustManager;
private ChooseLockSettingsHelper mChooseLockSettingsHelper; private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private Handler mHandler = new Handler(Looper.getMainLooper()); private Handler mHandler = new Handler(Looper.getMainLooper());
private String mTitle; private String mTitle;
private String mDetails; private String mDetails;
private int mUserId; private int mUserId;
private int mEffectiveUserId;
private int mCredentialMode; private int mCredentialMode;
private boolean mGoingToBackground; private boolean mGoingToBackground;
@@ -108,10 +108,16 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
showConfirmCredentials(); showConfirmCredentials();
} }
} }
} }
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
mTrustManager.setDeviceLockedForUser(mUserId, false);
ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, mUserManager,
mUserId);
ConfirmDeviceCredentialUtils.checkForPendingIntent(
ConfirmDeviceCredentialActivity.this);
setResult(Activity.RESULT_OK); setResult(Activity.RESULT_OK);
finish(); finish();
} }
@@ -124,6 +130,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
mBiometricManager = getSystemService(BiometricManager.class); mBiometricManager = getSystemService(BiometricManager.class);
mDevicePolicyManager = getSystemService(DevicePolicyManager.class); mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
mUserManager = UserManager.get(this); mUserManager = UserManager.get(this);
mTrustManager = getSystemService(TrustManager.class);
mLockPatternUtils = new LockPatternUtils(this); mLockPatternUtils = new LockPatternUtils(this);
Intent intent = getIntent(); Intent intent = getIntent();
@@ -134,7 +141,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction()); boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
mUserId = UserHandle.myUserId(); mUserId = UserHandle.myUserId();
mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId); final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
if (isInternalActivity()) { if (isInternalActivity()) {
try { try {
mUserId = Utils.getUserIdFromBundle(this, intent.getExtras()); mUserId = Utils.getUserIdFromBundle(this, intent.getExtras());
@@ -162,21 +169,23 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
} else if (isManagedProfile && isInternalActivity() } else if (isManagedProfile && isInternalActivity()
&& !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) { && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
mCredentialMode = CREDENTIAL_MANAGED; mCredentialMode = CREDENTIAL_MANAGED;
if (isBiometricAllowed()) { if (isBiometricAllowed(effectiveUserId)) {
showBiometricPrompt(); showBiometricPrompt();
launchedBiometric = true; launchedBiometric = true;
} else { } else {
showConfirmCredentials(); showConfirmCredentials();
launchedCDC = true;
} }
} else { } else {
mCredentialMode = CREDENTIAL_NORMAL; mCredentialMode = CREDENTIAL_NORMAL;
if (isBiometricAllowed()) { if (isBiometricAllowed(effectiveUserId)) {
// Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
// onAuthenticationError and do the right thing automatically. // onAuthenticationError and do the right thing automatically.
showBiometricPrompt(); showBiometricPrompt();
launchedBiometric = true; launchedBiometric = true;
} else { } else {
showConfirmCredentials(); showConfirmCredentials();
launchedCDC = true;
} }
} }
@@ -217,19 +226,20 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
// credential. Otherwise, biometric can't unlock fbe/keystore through // credential. Otherwise, biometric 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
// biometric is disabled due to device restart. // biometric is disabled due to device restart.
private boolean isStrongAuthRequired() { private boolean isStrongAuthRequired(int effectiveUserId) {
return !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId) return !mLockPatternUtils.isBiometricAllowedForUser(effectiveUserId)
|| !mUserManager.isUserUnlocked(mUserId); || !mUserManager.isUserUnlocked(mUserId);
} }
private boolean isBiometricDisabledByAdmin() { private boolean isBiometricDisabledByAdmin(int effectiveUserId) {
final int disabledFeatures = final int disabledFeatures =
mDevicePolicyManager.getKeyguardDisabledFeatures(null, mEffectiveUserId); mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0; return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0;
} }
private boolean isBiometricAllowed() { private boolean isBiometricAllowed(int effectiveUserId) {
return !isStrongAuthRequired() && !isBiometricDisabledByAdmin(); return !isStrongAuthRequired(effectiveUserId)
&& !isBiometricDisabledByAdmin(effectiveUserId);
} }
private void showBiometricPrompt() { private void showBiometricPrompt() {
@@ -250,6 +260,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
newFragment = true; newFragment = true;
} }
mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback); mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
mBiometricFragment.setUser(mUserId);
if (newFragment) { if (newFragment) {
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()

View File

@@ -18,17 +18,12 @@
package com.android.settings.password; package com.android.settings.password;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Dialog; import android.app.Dialog;
import android.app.IActivityManager;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
@@ -36,7 +31,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager; import android.os.UserManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
@@ -199,29 +193,6 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
public void startEnterAnimation() { 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) { private void setWorkChallengeBackground(View baseView, int userId) {
View mainContent = getActivity().findViewById(com.android.settings.R.id.main_content); View mainContent = getActivity().findViewById(com.android.settings.R.id.main_content);
if (mainContent != null) { 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() { protected void reportFailedAttempt() {
updateErrorMessage( updateErrorMessage(
mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1); mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);

View File

@@ -0,0 +1,65 @@
/*
* 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);
}
}
}

View File

@@ -434,10 +434,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
mPasswordEntryInputDisabler.setInputEnabled(true); mPasswordEntryInputDisabler.setInputEnabled(true);
if (matched) { if (matched) {
if (newResult) { if (newResult) {
reportSuccessfulAttempt(); ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
mUserManager, mEffectiveUserId);
} }
startDisappearAnimation(intent); startDisappearAnimation(intent);
checkForPendingIntent(); ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
} else { } else {
if (timeoutMs > 0) { if (timeoutMs > 0) {
refreshLockScreen(); refreshLockScreen();

View File

@@ -487,10 +487,11 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mLockPatternView.setEnabled(true); mLockPatternView.setEnabled(true);
if (matched) { if (matched) {
if (newResult) { if (newResult) {
reportSuccessfulAttempt(); ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
mUserManager, mEffectiveUserId);
} }
startDisappearAnimation(intent); startDisappearAnimation(intent);
checkForPendingIntent(); ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
} else { } else {
if (timeoutMs > 0) { if (timeoutMs > 0) {
refreshLockScreen(); refreshLockScreen();