3/n: Remove all faces when Pin/Pattern/Pass is removed

Bug: 110589286

Test: set up fingerprint + pass, change lock screen to swipe
      no regression, fingerprints are all removed, activity is finished()

Change-Id: Ie5e586b2f9d2c982d929e5c5b80911897889e7a4
This commit is contained in:
Kevin Chyn
2018-06-29 13:09:32 -07:00
parent 81dc0295d7
commit 0b95687f59

View File

@@ -32,6 +32,8 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.RemovalCallback; import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
@@ -145,6 +147,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private String mUserPassword; private String mUserPassword;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private FingerprintManager mFingerprintManager; private FingerprintManager mFingerprintManager;
private FaceManager mFaceManager;
private int mUserId; private int mUserId;
private boolean mHideDrawer = false; private boolean mHideDrawer = false;
private ManagedLockPasswordProvider mManagedPasswordProvider; private ManagedLockPasswordProvider mManagedPasswordProvider;
@@ -166,6 +169,7 @@ public class ChooseLockGeneric extends SettingsActivity {
String chooseLockAction = getActivity().getIntent().getAction(); String chooseLockAction = getActivity().getIntent().getAction();
mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity()); mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity());
mFaceManager = Utils.getFaceManagerOrNull(getActivity());
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity()); mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
mLockPatternUtils = new LockPatternUtils(getActivity()); mLockPatternUtils = new LockPatternUtils(getActivity());
@@ -636,6 +640,30 @@ public class ChooseLockGeneric extends SettingsActivity {
unlockMethodIntent); unlockMethodIntent);
} }
/**
* Keeps track of the biometric removal status. When all biometrics (including managed
* profiles) are removed, finishes the activity. Otherwise, it's possible the UI still
* shows enrolled biometrics due to the async remove.
*/
private class RemovalTracker {
boolean mFingerprintDone;
boolean mFaceDone;
void onFingerprintDone() {
mFingerprintDone = true;
if (mFingerprintDone && mFaceDone) {
finish();
}
}
void onFaceDone() {
mFaceDone = true;
if (mFingerprintDone && mFaceDone) {
finish();
}
}
}
/** /**
* Invokes an activity to change the user's pattern, password or PIN based on given quality * Invokes an activity to change the user's pattern, password or PIN based on given quality
* and minimum quality specified by DevicePolicyManager. If quality is * and minimum quality specified by DevicePolicyManager. If quality is
@@ -672,12 +700,18 @@ public class ChooseLockGeneric extends SettingsActivity {
mChooseLockSettingsHelper.utils().clearLock(mUserPassword, mUserId); mChooseLockSettingsHelper.utils().clearLock(mUserPassword, mUserId);
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId); mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
getActivity().setResult(Activity.RESULT_OK); getActivity().setResult(Activity.RESULT_OK);
removeAllFingerprintForUserAndFinish(mUserId); removeAllBiometricsForUserAndFinish(mUserId);
} else { } else {
removeAllFingerprintForUserAndFinish(mUserId); removeAllBiometricsForUserAndFinish(mUserId);
} }
} }
private void removeAllBiometricsForUserAndFinish(final int userId) {
final RemovalTracker tracker = new RemovalTracker();
removeAllFingerprintForUserAndFinish(userId, tracker);
removeAllFaceForUserAndFinish(userId, tracker);
}
private Intent getIntentForUnlockMethod(int quality) { private Intent getIntentForUnlockMethod(int quality) {
Intent intent = null; Intent intent = null;
if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
@@ -693,7 +727,8 @@ public class ChooseLockGeneric extends SettingsActivity {
return intent; return intent;
} }
private void removeAllFingerprintForUserAndFinish(final int userId) { private void removeAllFingerprintForUserAndFinish(final int userId,
RemovalTracker tracker) {
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) { if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
if (mFingerprintManager.hasEnrolledFingerprints(userId)) { if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
mFingerprintManager.setActiveUser(userId); mFingerprintManager.setActiveUser(userId);
@@ -715,25 +750,27 @@ public class ChooseLockGeneric extends SettingsActivity {
@Override @Override
public void onRemovalSucceeded(Fingerprint fp, int remaining) { public void onRemovalSucceeded(Fingerprint fp, int remaining) {
if (remaining == 0) { if (remaining == 0) {
removeManagedProfileFingerprintsAndFinishIfNecessary(userId); removeManagedProfileFingerprintsAndFinishIfNecessary(userId,
tracker);
} }
} }
}); });
} else { } else {
// No fingerprints in this user, we may also want to delete managed profile // No fingerprints in this user, we may also want to delete managed profile
// fingerprints // fingerprints
removeManagedProfileFingerprintsAndFinishIfNecessary(userId); removeManagedProfileFingerprintsAndFinishIfNecessary(userId, tracker);
} }
} else { } else {
// The removal callback will call finish, once all fingerprints are removed. // The removal callback will call finish, once all fingerprints are removed.
// We need to wait for that to occur, otherwise, the UI will still show that // We need to wait for that to occur, otherwise, the UI will still show that
// fingerprints exist even though they are (about to) be removed depending on // fingerprints exist even though they are (about to) be removed depending on
// the race condition. // the race condition.
finish(); tracker.onFingerprintDone();
} }
} }
private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId) { private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId,
RemovalTracker tracker) {
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) { if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
mFingerprintManager.setActiveUser(UserHandle.myUserId()); mFingerprintManager.setActiveUser(UserHandle.myUserId());
} }
@@ -746,14 +783,69 @@ public class ChooseLockGeneric extends SettingsActivity {
final UserInfo userInfo = profiles.get(i); final UserInfo userInfo = profiles.get(i);
if (userInfo.isManagedProfile() && !mLockPatternUtils if (userInfo.isManagedProfile() && !mLockPatternUtils
.isSeparateProfileChallengeEnabled(userInfo.id)) { .isSeparateProfileChallengeEnabled(userInfo.id)) {
removeAllFingerprintForUserAndFinish(userInfo.id); removeAllFingerprintForUserAndFinish(userInfo.id, tracker);
hasChildProfile = true; hasChildProfile = true;
break; break;
} }
} }
} }
if (!hasChildProfile) { if (!hasChildProfile) {
finish(); tracker.onFingerprintDone();
}
}
// TODO: figure out how to eliminate duplicated code. It's a bit hard due to the async-ness
private void removeAllFaceForUserAndFinish(final int userId, RemovalTracker tracker) {
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
if (mFaceManager.hasEnrolledFaces(userId)) {
mFaceManager.setActiveUser(userId);
Face face = new Face(null, 0, 0);
mFaceManager.remove(face, userId,
new FaceManager.RemovalCallback() {
@Override
public void onRemovalError(Face face, int errMsgId, CharSequence err) {
Log.e(TAG, String.format("Can't remove face %d. Reason: %s",
face.getBiometricId(), err));
}
@Override
public void onRemovalSucceeded(Face face, int remaining) {
if (remaining == 0) {
removeManagedProfileFacesAndFinishIfNecessary(userId, tracker);
}
}
});
} else {
// No faces in this user, we may also want to delete managed profile faces
removeManagedProfileFacesAndFinishIfNecessary(userId, tracker);
}
} else {
tracker.onFaceDone();
}
}
// TODO: figure out how to eliminate duplicated code. It's a bit hard due to the async-ness
private void removeManagedProfileFacesAndFinishIfNecessary(final int parentUserId,
RemovalTracker tracker) {
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
mFaceManager.setActiveUser(UserHandle.myUserId());
}
boolean hasChildProfile = false;
if (!mUserManager.getUserInfo(parentUserId).isManagedProfile()) {
// Current user is primary profile, remove work profile faces if necessary
final List<UserInfo> profiles = mUserManager.getProfiles(parentUserId);
final int profilesSize = profiles.size();
for (int i = 0; i < profilesSize; i++) {
final UserInfo userInfo = profiles.get(i);
if (userInfo.isManagedProfile() && !mLockPatternUtils
.isSeparateProfileChallengeEnabled(userInfo.id)) {
removeAllFaceForUserAndFinish(userInfo.id, tracker);
hasChildProfile = true;
break;
}
}
}
if (!hasChildProfile) {
tracker.onFaceDone();
} }
} }