Fix DPM.ACTION_SET_NEW_PASSWORD
Problem: SetNewPasswordActivity is the new entrance for ACTION_SET_NEW_PASSWORD. And it starts ChooseLockGeneric with the fingerprint extras. ChooseLockGeneric infers which user is starting it and determine which user is setting password. However, it now always think that it is current user as it is always SetNewPasswordActivity in current user starting it. Solution: Resolve the user id in SetNewPasswordActivity and forward it to ChooseLockGeneric. SetNewPasswordActivity needs to know the user id anyway in order to have the fingerprint checking in the correct user id. Test: 1. make RunSettingsRoboTests 2. Manual Test a. Start SET_NEW_PASSWORD intent in user 0, set password. User 0 password is set. b. Start SET_NEW_PASSWORD intent in work profile, set password. work profile password is set. c. SET_PROFILE_PARENT_NEW_PASSWORD is always setting parent password. d. If fingerprint is disabled, both intent should not show fingerprint option e. DO sync auth flow with google.com account, fingerprint option is shown. Change-Id: I2f73d01ab11e91b337beb90c05bbcb857dfd40dc Fix: 32959373
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.annotation.NonNull;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Wrapper of {@link FingerprintManager}. Workaround for roboelectic testing. See
|
||||
* {@link IFingerprintManager} for details.
|
||||
*/
|
||||
public class FingerprintManagerWrapper implements IFingerprintManager {
|
||||
private @NonNull FingerprintManager mFingerprintManager;
|
||||
|
||||
public FingerprintManagerWrapper(@NonNull FingerprintManager fingerprintManager) {
|
||||
Preconditions.checkNotNull(fingerprintManager);
|
||||
mFingerprintManager = fingerprintManager;
|
||||
}
|
||||
|
||||
public boolean isHardwareDetected() {
|
||||
return mFingerprintManager.isHardwareDetected();
|
||||
}
|
||||
|
||||
public boolean hasEnrolledFingerprints(int userId) {
|
||||
return mFingerprintManager.hasEnrolledFingerprints(userId);
|
||||
}
|
||||
|
||||
public long preEnroll() {
|
||||
return mFingerprintManager.preEnroll();
|
||||
}
|
||||
}
|
31
src/com/android/settings/password/IFingerprintManager.java
Normal file
31
src/com/android/settings/password/IFingerprintManager.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
/**
|
||||
* This is the workaround to allow us test {@link SetNewPasswordController} which uses a new hidden
|
||||
* API {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints(int)} that
|
||||
* roboelectric does not support yet. Having roboelectic to support latest platform API is tracked
|
||||
* in b/30995831.
|
||||
*/
|
||||
public interface IFingerprintManager {
|
||||
boolean isHardwareDetected();
|
||||
|
||||
boolean hasEnrolledFingerprints(int userId);
|
||||
|
||||
long preEnroll();
|
||||
}
|
@@ -16,23 +16,26 @@
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.ChooseLockGeneric;
|
||||
import com.android.settings.SetupChooseLockGeneric;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and
|
||||
* {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} intent to the appropriate UI
|
||||
* activity for handling set new password.
|
||||
*/
|
||||
public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui {
|
||||
private static final String TAG = "SetNewPasswordActivity";
|
||||
private String mNewPasswordAction;
|
||||
private SetNewPasswordController mSetNewPasswordController;
|
||||
|
||||
@@ -41,19 +44,23 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo
|
||||
super.onCreate(savedState);
|
||||
|
||||
mNewPasswordAction = getIntent().getAction();
|
||||
mSetNewPasswordController = new SetNewPasswordController(this, this);
|
||||
if (!ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
|
||||
&& !ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) {
|
||||
Log.e(TAG, "Unexpected action to launch this activity");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mSetNewPasswordController = SetNewPasswordController.create(this, this, getIntent());
|
||||
mSetNewPasswordController.dispatchSetNewPasswordIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras) {
|
||||
public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
|
||||
final boolean isInSetupWizard = !Utils.isDeviceProvisioned(this);
|
||||
Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class)
|
||||
: new Intent(this, ChooseLockGeneric.class);
|
||||
intent.setAction(mNewPasswordAction);
|
||||
if (chooseLockFingerprintExtras != null) {
|
||||
intent.putExtras(chooseLockFingerprintExtras);
|
||||
}
|
||||
intent.putExtras(chooseLockFingerprintExtras);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
@@ -16,18 +16,23 @@
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.ChooseLockGeneric;
|
||||
import com.android.settings.ChooseLockSettingsHelper;
|
||||
import com.android.settings.Utils;
|
||||
@@ -43,31 +48,52 @@ final class SetNewPasswordController {
|
||||
|
||||
interface Ui {
|
||||
/** Starts the {@link ChooseLockGeneric} activity with the given extras. */
|
||||
void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras);
|
||||
void launchChooseLock(Bundle chooseLockFingerprintExtras);
|
||||
}
|
||||
|
||||
private final int mCurrentUserId;
|
||||
/**
|
||||
* Which user is setting new password.
|
||||
*/
|
||||
private final int mTargetUserId;
|
||||
private final PackageManager mPackageManager;
|
||||
@Nullable private final FingerprintManager mFingerprintManager;
|
||||
@Nullable private final IFingerprintManager mFingerprintManager;
|
||||
private final DevicePolicyManager mDevicePolicyManager;
|
||||
private final Ui mUi;
|
||||
|
||||
public SetNewPasswordController(Context context, Ui ui) {
|
||||
this(context.getUserId(),
|
||||
public static SetNewPasswordController create(Context context, Ui ui, Intent intent) {
|
||||
// Trying to figure out which user is setting new password. If it is
|
||||
// ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or the calling user is not allowed to set
|
||||
// separate profile challenge, it is the current user to set new password. Otherwise,
|
||||
// it is the user who starts this activity setting new password.
|
||||
int userId = ActivityManager.getCurrentUser();
|
||||
if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) {
|
||||
final int callingUserId = Utils.getSecureTargetUser(context.getActivityToken(),
|
||||
UserManager.get(context), null, intent.getExtras()).getIdentifier();
|
||||
final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
|
||||
if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) {
|
||||
userId = callingUserId;
|
||||
}
|
||||
}
|
||||
// Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details.
|
||||
final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
final IFingerprintManager fingerprintManagerWrapper =
|
||||
fingerprintManager == null
|
||||
? null
|
||||
: new FingerprintManagerWrapper(fingerprintManager);
|
||||
return new SetNewPasswordController(userId,
|
||||
context.getPackageManager(),
|
||||
Utils.getFingerprintManagerOrNull(context),
|
||||
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE),
|
||||
ui);
|
||||
fingerprintManagerWrapper,
|
||||
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SetNewPasswordController(
|
||||
int currentUserId,
|
||||
int targetUserId,
|
||||
PackageManager packageManager,
|
||||
FingerprintManager fingerprintManager,
|
||||
IFingerprintManager fingerprintManager,
|
||||
DevicePolicyManager devicePolicyManager,
|
||||
Ui ui) {
|
||||
mCurrentUserId = currentUserId;
|
||||
mTargetUserId = targetUserId;
|
||||
mPackageManager = checkNotNull(packageManager);
|
||||
mFingerprintManager = fingerprintManager;
|
||||
mDevicePolicyManager = checkNotNull(devicePolicyManager);
|
||||
@@ -78,38 +104,38 @@ final class SetNewPasswordController {
|
||||
* Dispatches the set new password intent to the correct activity that handles it.
|
||||
*/
|
||||
public void dispatchSetNewPasswordIntent() {
|
||||
final Bundle extras;
|
||||
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
|
||||
&& mFingerprintManager != null
|
||||
&& mFingerprintManager.isHardwareDetected()
|
||||
&& !mFingerprintManager.hasEnrolledFingerprints()
|
||||
&& !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
|
||||
&& !isFingerprintDisabledByAdmin()) {
|
||||
mUi.launchChooseLock(getFingerprintChooseLockExtras());
|
||||
extras = getFingerprintChooseLockExtras();
|
||||
} else {
|
||||
mUi.launchChooseLock(null);
|
||||
extras = new Bundle();
|
||||
}
|
||||
// No matter we show fingerprint options or not, we should tell the next activity which
|
||||
// user is setting new password.
|
||||
extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
|
||||
mUi.launchChooseLock(extras);
|
||||
}
|
||||
|
||||
private Bundle getFingerprintChooseLockExtras() {
|
||||
Bundle chooseLockExtras = new Bundle();
|
||||
if (mFingerprintManager != null) {
|
||||
long challenge = mFingerprintManager.preEnroll();
|
||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||
chooseLockExtras.putBoolean(
|
||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
|
||||
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||
if (mCurrentUserId != UserHandle.USER_NULL) {
|
||||
chooseLockExtras.putInt(Intent.EXTRA_USER_ID, mCurrentUserId);
|
||||
}
|
||||
}
|
||||
long challenge = mFingerprintManager.preEnroll();
|
||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
PASSWORD_QUALITY_SOMETHING);
|
||||
chooseLockExtras.putBoolean(
|
||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
|
||||
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||
return chooseLockExtras;
|
||||
}
|
||||
|
||||
private boolean isFingerprintDisabledByAdmin() {
|
||||
int disabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures(
|
||||
null, mCurrentUserId);
|
||||
return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
|
||||
int disabledFeatures =
|
||||
mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
|
||||
return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user