DO NOT MERGE: Fix DPM.ACTION_SET_NEW_PASSWORD
This is a cherry-pick of ag/1640561. 1. Context.getActivityToken is not available in n mr2, passed the token from the activity to the controller instead. 2. Haven't pick the tests from master to mr2 branch because robotest is not set up in mr2 branch. Fix: 32959373 Change-Id: I2f73d01ab11e91b337beb90c05bbcb857dfd40dc
This commit is contained in:
@@ -186,22 +186,15 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
ENCRYPT_REQUESTED_DISABLED);
|
||||
}
|
||||
|
||||
int targetUser = Utils.getSecureTargetUser(
|
||||
// a) If this is started from other user, use that user id.
|
||||
// b) If this is started from the same user, read the extra if this is launched
|
||||
// from Settings app itself.
|
||||
// c) Otherwise, use UserHandle.myUserId().
|
||||
mUserId = Utils.getSecureTargetUser(
|
||||
getActivity().getActivityToken(),
|
||||
UserManager.get(getActivity()),
|
||||
null,
|
||||
getArguments(),
|
||||
getActivity().getIntent().getExtras()).getIdentifier();
|
||||
if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
|
||||
|| !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) {
|
||||
// Always use parent if explicitely requested or if profile challenge is not
|
||||
// supported
|
||||
Bundle arguments = getArguments();
|
||||
mUserId = Utils.getUserIdFromBundle(getContext(), arguments != null ? arguments
|
||||
: getActivity().getIntent().getExtras());
|
||||
} else {
|
||||
mUserId = targetUser;
|
||||
}
|
||||
|
||||
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
|
||||
&& Utils.isManagedProfile(UserManager.get(getActivity()), mUserId)
|
||||
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
|
||||
@@ -256,6 +249,8 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
} else if (KEY_SKIP_FINGERPRINT.equals(key)) {
|
||||
Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
|
||||
chooseLockGenericIntent.setAction(getIntent().getAction());
|
||||
// Forward the target user id to ChooseLockGeneric.
|
||||
chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
|
||||
startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
|
||||
return true;
|
||||
@@ -343,6 +338,8 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
if (data != null) {
|
||||
intent.putExtras(data.getExtras());
|
||||
}
|
||||
// Forward the target user id to fingerprint setup page.
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
} else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
|
||||
|
@@ -102,6 +102,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static android.content.Intent.EXTRA_USER;
|
||||
import static android.content.Intent.EXTRA_USER_ID;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||
|
||||
@@ -651,10 +652,15 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
|
||||
/**
|
||||
* Returns the target user for a Settings activity.
|
||||
*
|
||||
* The target user can be either the current user, the user that launched this activity or
|
||||
* the user contained as an extra in the arguments or intent extras.
|
||||
*
|
||||
* <p>
|
||||
* User would be retrieved in this order:
|
||||
* <ul>
|
||||
* <li> If this activity is launched from other user, return that user id.
|
||||
* <li> If this is launched from the Settings app in same user, return the user contained as an
|
||||
* extra in the arguments or intent extras.
|
||||
* <li> Otherwise, return UserHandle.myUserId().
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note: This is secure in the sense that it only returns a target user different to the current
|
||||
* one if the app launching this activity is the Settings app itself, running in the same user
|
||||
* or in one that is in the same profile group, or if the user id is provided by the system.
|
||||
@@ -675,16 +681,14 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
return launchedFromUser;
|
||||
}
|
||||
}
|
||||
UserHandle extrasUser = intentExtras != null
|
||||
? (UserHandle) intentExtras.getParcelable(EXTRA_USER) : null;
|
||||
UserHandle extrasUser = getUserHandleFromBundle(intentExtras);
|
||||
if (extrasUser != null && !extrasUser.equals(currentUser)) {
|
||||
// Check it's secure
|
||||
if (launchedFromSettingsApp && isProfileOf(um, extrasUser)) {
|
||||
return extrasUser;
|
||||
}
|
||||
}
|
||||
UserHandle argumentsUser = arguments != null
|
||||
? (UserHandle) arguments.getParcelable(EXTRA_USER) : null;
|
||||
UserHandle argumentsUser = getUserHandleFromBundle(arguments);
|
||||
if (argumentsUser != null && !argumentsUser.equals(currentUser)) {
|
||||
// Check it's secure
|
||||
if (launchedFromSettingsApp && isProfileOf(um, argumentsUser)) {
|
||||
@@ -698,6 +702,25 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup both {@link Intent#EXTRA_USER} and {@link Intent#EXTRA_USER_ID} in the bundle
|
||||
* and return the {@link UserHandle} object. Return {@code null} if nothing is found.
|
||||
*/
|
||||
private static @Nullable UserHandle getUserHandleFromBundle(Bundle bundle) {
|
||||
if (bundle == null) {
|
||||
return null;
|
||||
}
|
||||
final UserHandle user = bundle.getParcelable(EXTRA_USER);
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
final int userId = bundle.getInt(EXTRA_USER_ID, -1);
|
||||
if (userId != -1) {
|
||||
return UserHandle.of(userId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target user for a Settings activity.
|
||||
*
|
||||
|
@@ -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,13 +16,18 @@
|
||||
|
||||
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
|
||||
@@ -30,6 +35,7 @@ import com.android.settings.ChooseLockGeneric;
|
||||
* 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;
|
||||
|
||||
@@ -38,17 +44,22 @@ 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(), getActivityToken());
|
||||
mSetNewPasswordController.dispatchSetNewPasswordIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras) {
|
||||
public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
|
||||
Intent intent = new Intent(this, ChooseLockGeneric.class)
|
||||
.setAction(mNewPasswordAction);
|
||||
if (chooseLockFingerprintExtras != null) {
|
||||
intent.putExtras(chooseLockFingerprintExtras);
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
@@ -16,20 +16,27 @@
|
||||
|
||||
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.IBinder;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Business logic for {@link SetNewPasswordActivity}.
|
||||
@@ -42,31 +49,54 @@ 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,
|
||||
IBinder activityToken) {
|
||||
// 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(activityToken,
|
||||
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 =
|
||||
(FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
|
||||
final IFingerprintManager fingerprintManagerWrapper =
|
||||
fingerprintManager == null
|
||||
? null
|
||||
: new FingerprintManagerWrapper(fingerprintManager);
|
||||
return new SetNewPasswordController(userId,
|
||||
context.getPackageManager(),
|
||||
(FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE),
|
||||
(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);
|
||||
@@ -77,38 +107,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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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