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:
Tony Mak
2016-11-23 11:36:18 +00:00
parent 9a35bc6552
commit 8f41b9b665
8 changed files with 231 additions and 80 deletions

View File

@@ -185,22 +185,15 @@ public class ChooseLockGeneric extends SettingsActivity {
ENCRYPT_REQUESTED_DISABLED); 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(), getActivity().getActivityToken(),
UserManager.get(getActivity()), UserManager.get(getActivity()),
null, getArguments(),
getActivity().getIntent().getExtras()).getIdentifier(); 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) if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
&& UserManager.get(getActivity()).isManagedProfile(mUserId) && UserManager.get(getActivity()).isManagedProfile(mUserId)
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) { && mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
@@ -255,6 +248,8 @@ public class ChooseLockGeneric extends SettingsActivity {
} else if (KEY_SKIP_FINGERPRINT.equals(key)) { } else if (KEY_SKIP_FINGERPRINT.equals(key)) {
Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class); Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
chooseLockGenericIntent.setAction(getIntent().getAction()); chooseLockGenericIntent.setAction(getIntent().getAction());
// Forward the target user id to ChooseLockGeneric.
chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed); chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST); startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
return true; return true;
@@ -342,6 +337,8 @@ public class ChooseLockGeneric extends SettingsActivity {
if (data != null) { if (data != null) {
intent.putExtras(data.getExtras()); intent.putExtras(data.getExtras());
} }
// Forward the target user id to fingerprint setup page.
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
startActivity(intent); startActivity(intent);
finish(); finish();
} else if (requestCode == SKIP_FINGERPRINT_REQUEST) { } else if (requestCode == SKIP_FINGERPRINT_REQUEST) {

View File

@@ -104,6 +104,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import static android.content.Intent.EXTRA_USER; 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_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE; import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -636,16 +637,21 @@ public final class Utils extends com.android.settingslib.Utils {
/** /**
* Returns the target user for a Settings activity. * Returns the target user for a Settings activity.
* * <p>
* The target user can be either the current user, the user that launched this activity or * User would be retrieved in this order:
* the user contained as an extra in the arguments or intent extras. * <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 * 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 * 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. * or in one that is in the same profile group, or if the user id is provided by the system.
*/ */
public static UserHandle getSecureTargetUser(IBinder activityToken, public static UserHandle getSecureTargetUser(IBinder activityToken,
UserManager um, @Nullable Bundle arguments, @Nullable Bundle intentExtras) { UserManager um, @Nullable Bundle arguments, @Nullable Bundle intentExtras) {
UserHandle currentUser = new UserHandle(UserHandle.myUserId()); UserHandle currentUser = new UserHandle(UserHandle.myUserId());
IActivityManager am = ActivityManager.getService(); IActivityManager am = ActivityManager.getService();
try { try {
@@ -660,16 +666,14 @@ public final class Utils extends com.android.settingslib.Utils {
return launchedFromUser; return launchedFromUser;
} }
} }
UserHandle extrasUser = intentExtras != null UserHandle extrasUser = getUserHandleFromBundle(intentExtras);
? (UserHandle) intentExtras.getParcelable(EXTRA_USER) : null;
if (extrasUser != null && !extrasUser.equals(currentUser)) { if (extrasUser != null && !extrasUser.equals(currentUser)) {
// Check it's secure // Check it's secure
if (launchedFromSettingsApp && isProfileOf(um, extrasUser)) { if (launchedFromSettingsApp && isProfileOf(um, extrasUser)) {
return extrasUser; return extrasUser;
} }
} }
UserHandle argumentsUser = arguments != null UserHandle argumentsUser = getUserHandleFromBundle(arguments);
? (UserHandle) arguments.getParcelable(EXTRA_USER) : null;
if (argumentsUser != null && !argumentsUser.equals(currentUser)) { if (argumentsUser != null && !argumentsUser.equals(currentUser)) {
// Check it's secure // Check it's secure
if (launchedFromSettingsApp && isProfileOf(um, argumentsUser)) { if (launchedFromSettingsApp && isProfileOf(um, argumentsUser)) {
@@ -681,7 +685,26 @@ public final class Utils extends com.android.settingslib.Utils {
Log.v(TAG, "Could not talk to activity manager.", e); Log.v(TAG, "Could not talk to activity manager.", e);
} }
return currentUser; 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. * Returns the target user for a Settings activity.

View File

@@ -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();
}
}

View 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();
}

View File

@@ -16,23 +16,26 @@
package com.android.settings.password; 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.Activity;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import com.android.settings.ChooseLockGeneric; import com.android.settings.ChooseLockGeneric;
import com.android.settings.SetupChooseLockGeneric; import com.android.settings.SetupChooseLockGeneric;
import com.android.settings.Utils; import com.android.settings.Utils;
/** /**
* Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and * Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and
* {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} intent to the appropriate UI * {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} intent to the appropriate UI
* activity for handling set new password. * activity for handling set new password.
*/ */
public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui { public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui {
private static final String TAG = "SetNewPasswordActivity";
private String mNewPasswordAction; private String mNewPasswordAction;
private SetNewPasswordController mSetNewPasswordController; private SetNewPasswordController mSetNewPasswordController;
@@ -41,19 +44,23 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo
super.onCreate(savedState); super.onCreate(savedState);
mNewPasswordAction = getIntent().getAction(); 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(); mSetNewPasswordController.dispatchSetNewPasswordIntent();
} }
@Override @Override
public void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras) { public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
final boolean isInSetupWizard = !Utils.isDeviceProvisioned(this); final boolean isInSetupWizard = !Utils.isDeviceProvisioned(this);
Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class) Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class)
: new Intent(this, ChooseLockGeneric.class); : new Intent(this, ChooseLockGeneric.class);
intent.setAction(mNewPasswordAction); intent.setAction(mNewPasswordAction);
if (chooseLockFingerprintExtras != null) { intent.putExtras(chooseLockFingerprintExtras);
intent.putExtras(chooseLockFingerprintExtras);
}
startActivity(intent); startActivity(intent);
finish(); finish();
} }

View File

@@ -16,18 +16,23 @@
package com.android.settings.password; 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 static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager; 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.PackageManager; import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.ChooseLockGeneric; import com.android.settings.ChooseLockGeneric;
import com.android.settings.ChooseLockSettingsHelper; import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.Utils; import com.android.settings.Utils;
@@ -43,31 +48,52 @@ final class SetNewPasswordController {
interface Ui { interface Ui {
/** Starts the {@link ChooseLockGeneric} activity with the given extras. */ /** 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; private final PackageManager mPackageManager;
@Nullable private final FingerprintManager mFingerprintManager; @Nullable private final IFingerprintManager mFingerprintManager;
private final DevicePolicyManager mDevicePolicyManager; private final DevicePolicyManager mDevicePolicyManager;
private final Ui mUi; private final Ui mUi;
public SetNewPasswordController(Context context, Ui ui) { public static SetNewPasswordController create(Context context, Ui ui, Intent intent) {
this(context.getUserId(), // 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(), context.getPackageManager(),
Utils.getFingerprintManagerOrNull(context), fingerprintManagerWrapper,
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
ui);
} }
@VisibleForTesting @VisibleForTesting
SetNewPasswordController( SetNewPasswordController(
int currentUserId, int targetUserId,
PackageManager packageManager, PackageManager packageManager,
FingerprintManager fingerprintManager, IFingerprintManager fingerprintManager,
DevicePolicyManager devicePolicyManager, DevicePolicyManager devicePolicyManager,
Ui ui) { Ui ui) {
mCurrentUserId = currentUserId; mTargetUserId = targetUserId;
mPackageManager = checkNotNull(packageManager); mPackageManager = checkNotNull(packageManager);
mFingerprintManager = fingerprintManager; mFingerprintManager = fingerprintManager;
mDevicePolicyManager = checkNotNull(devicePolicyManager); mDevicePolicyManager = checkNotNull(devicePolicyManager);
@@ -78,38 +104,38 @@ final class SetNewPasswordController {
* Dispatches the set new password intent to the correct activity that handles it. * Dispatches the set new password intent to the correct activity that handles it.
*/ */
public void dispatchSetNewPasswordIntent() { public void dispatchSetNewPasswordIntent() {
final Bundle extras;
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
&& mFingerprintManager != null && mFingerprintManager != null
&& mFingerprintManager.isHardwareDetected() && mFingerprintManager.isHardwareDetected()
&& !mFingerprintManager.hasEnrolledFingerprints() && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
&& !isFingerprintDisabledByAdmin()) { && !isFingerprintDisabledByAdmin()) {
mUi.launchChooseLock(getFingerprintChooseLockExtras()); extras = getFingerprintChooseLockExtras();
} else { } 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() { private Bundle getFingerprintChooseLockExtras() {
Bundle chooseLockExtras = new Bundle(); Bundle chooseLockExtras = new Bundle();
if (mFingerprintManager != null) { long challenge = mFingerprintManager.preEnroll();
long challenge = mFingerprintManager.preEnroll(); chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, PASSWORD_QUALITY_SOMETHING);
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); chooseLockExtras.putBoolean(
chooseLockExtras.putBoolean( ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
if (mCurrentUserId != UserHandle.USER_NULL) {
chooseLockExtras.putInt(Intent.EXTRA_USER_ID, mCurrentUserId);
}
}
return chooseLockExtras; return chooseLockExtras;
} }
private boolean isFingerprintDisabledByAdmin() { private boolean isFingerprintDisabledByAdmin() {
int disabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures( int disabledFeatures =
null, mCurrentUserId); mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0; return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
} }
} }

View File

@@ -18,6 +18,7 @@ package com.android.settings.password;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import com.android.settings.ChooseLockGeneric; import com.android.settings.ChooseLockGeneric;
@@ -59,7 +60,9 @@ public class SetNewPasswordActivityTest {
public void testChooseLockGeneric() { public void testChooseLockGeneric() {
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1); Settings.Global.DEVICE_PROVISIONED, 1);
SetNewPasswordActivity activity = Robolectric.setupActivity(SetNewPasswordActivity.class); SetNewPasswordActivity activity =
Robolectric.buildActivity(SetNewPasswordActivity.class).get();
activity.launchChooseLock(new Bundle());
ShadowActivity shadowActivity = shadowOf(activity); ShadowActivity shadowActivity = shadowOf(activity);
Intent intent = shadowActivity.getNextStartedActivityForResult().intent; Intent intent = shadowActivity.getNextStartedActivityForResult().intent;
@@ -71,7 +74,9 @@ public class SetNewPasswordActivityTest {
public void testSetupChooseLockGeneric() { public void testSetupChooseLockGeneric() {
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0); Settings.Global.DEVICE_PROVISIONED, 0);
SetNewPasswordActivity activity = Robolectric.setupActivity(SetNewPasswordActivity.class); SetNewPasswordActivity activity =
Robolectric.buildActivity(SetNewPasswordActivity.class).get();
activity.launchChooseLock(new Bundle());
ShadowActivity shadowActivity = shadowOf(activity); ShadowActivity shadowActivity = shadowOf(activity);
Intent intent = shadowActivity.getNextStartedActivityForResult().intent; Intent intent = shadowActivity.getNextStartedActivityForResult().intent;

View File

@@ -20,10 +20,11 @@ import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle; import android.os.Bundle;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -38,6 +39,7 @@ import static com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment.M
import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE; import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE;
import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT; import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE; import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
@@ -45,17 +47,18 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
/** /**
* Tests for {@link SetNewPasswordController}. * Tests for {@link SetNewPasswordController}.
*/ */
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public final class SetNewPasswordControllerTest { public final class SetNewPasswordControllerTest {
private static final int CURRENT_UID = 101; private static final int CURRENT_USER_ID = 101;
private static final long FINGERPRINT_CHALLENGE = -9876512313131L; private static final long FINGERPRINT_CHALLENGE = -9876512313131L;
@Mock PackageManager mPackageManager; @Mock PackageManager mPackageManager;
@Mock FingerprintManager mFingerprintManager; @Mock IFingerprintManager mFingerprintManager;
@Mock DevicePolicyManager mDevicePolicyManager; @Mock DevicePolicyManager mDevicePolicyManager;
@Mock private SetNewPasswordController.Ui mUi; @Mock private SetNewPasswordController.Ui mUi;
@@ -64,9 +67,8 @@ public final class SetNewPasswordControllerTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mSetNewPasswordController = new SetNewPasswordController( mSetNewPasswordController = new SetNewPasswordController(
CURRENT_UID, mPackageManager, mFingerprintManager, mDevicePolicyManager, mUi); CURRENT_USER_ID, mPackageManager, mFingerprintManager, mDevicePolicyManager, mUi);
when(mFingerprintManager.preEnroll()).thenReturn(FINGERPRINT_CHALLENGE); when(mFingerprintManager.preEnroll()).thenReturn(FINGERPRINT_CHALLENGE);
when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true); when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true);
@@ -77,7 +79,7 @@ public final class SetNewPasswordControllerTest {
// GIVEN the device supports fingerprint. // GIVEN the device supports fingerprint.
when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
// GIVEN there are no enrolled fingerprints. // GIVEN there are no enrolled fingerprints.
when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false); when(mFingerprintManager.hasEnrolledFingerprints(CURRENT_USER_ID)).thenReturn(false);
// GIVEN DPC does not disallow fingerprint for keyguard usage. // GIVEN DPC does not disallow fingerprint for keyguard usage.
when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class))) when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
.thenReturn(0); .thenReturn(0);
@@ -101,7 +103,9 @@ public final class SetNewPasswordControllerTest {
mSetNewPasswordController.dispatchSetNewPasswordIntent(); mSetNewPasswordController.dispatchSetNewPasswordIntent();
// THEN the choose lock activity is launched without fingerprint extras. // THEN the choose lock activity is launched without fingerprint extras.
verify(mUi).launchChooseLock(null); ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(mUi).launchChooseLock(bundleArgumentCaptor.capture());
assertBundleContainsUserIdOnly(bundleArgumentCaptor.getValue());
} }
@Test @Test
@@ -109,7 +113,7 @@ public final class SetNewPasswordControllerTest {
// GIVEN the device does NOT support fingerprint. // GIVEN the device does NOT support fingerprint.
when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
// GIVEN there are no enrolled fingerprints. // GIVEN there are no enrolled fingerprints.
when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false); when(mFingerprintManager.hasEnrolledFingerprints(CURRENT_USER_ID)).thenReturn(false);
// GIVEN DPC does not disallow fingerprint for keyguard usage. // GIVEN DPC does not disallow fingerprint for keyguard usage.
when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class))) when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
.thenReturn(0); .thenReturn(0);
@@ -117,8 +121,10 @@ public final class SetNewPasswordControllerTest {
// WHEN the controller dispatches a set new password intent. // WHEN the controller dispatches a set new password intent.
mSetNewPasswordController.dispatchSetNewPasswordIntent(); mSetNewPasswordController.dispatchSetNewPasswordIntent();
// THEN the choose lock activity is launched without fingerprint extras. // THEN the choose lock activity is launched without a bundle contains user id only.
verify(mUi).launchChooseLock(null); ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(mUi).launchChooseLock(bundleArgumentCaptor.capture());
assertBundleContainsUserIdOnly(bundleArgumentCaptor.getValue());
} }
@Test @Test
@@ -126,7 +132,7 @@ public final class SetNewPasswordControllerTest {
// GIVEN the device supports fingerprint. // GIVEN the device supports fingerprint.
when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
// GIVEN there are no enrolled fingerprints. // GIVEN there are no enrolled fingerprints.
when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true); when(mFingerprintManager.hasEnrolledFingerprints(CURRENT_USER_ID)).thenReturn(true);
// GIVEN DPC does not disallow fingerprint for keyguard usage. // GIVEN DPC does not disallow fingerprint for keyguard usage.
when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class))) when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
.thenReturn(0); .thenReturn(0);
@@ -134,8 +140,10 @@ public final class SetNewPasswordControllerTest {
// WHEN the controller dispatches a set new password intent. // WHEN the controller dispatches a set new password intent.
mSetNewPasswordController.dispatchSetNewPasswordIntent(); mSetNewPasswordController.dispatchSetNewPasswordIntent();
// THEN the choose lock activity is launched without fingerprint extras. // THEN the choose lock activity is launched without a bundle contains user id only.
verify(mUi).launchChooseLock(null); ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(mUi).launchChooseLock(bundleArgumentCaptor.capture());
assertBundleContainsUserIdOnly(bundleArgumentCaptor.getValue());
} }
@Test @Test
@@ -143,7 +151,7 @@ public final class SetNewPasswordControllerTest {
// GIVEN the device supports fingerprint. // GIVEN the device supports fingerprint.
when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
// GIVEN there is an enrolled fingerprint. // GIVEN there is an enrolled fingerprint.
when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true); when(mFingerprintManager.hasEnrolledFingerprints(CURRENT_USER_ID)).thenReturn(true);
// GIVEN DPC disallows fingerprint for keyguard usage. // GIVEN DPC disallows fingerprint for keyguard usage.
when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class))) when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
@@ -151,8 +159,10 @@ public final class SetNewPasswordControllerTest {
// WHEN the controller dispatches a set new password intent. // WHEN the controller dispatches a set new password intent.
mSetNewPasswordController.dispatchSetNewPasswordIntent(); mSetNewPasswordController.dispatchSetNewPasswordIntent();
// THEN the choose lock activity is launched without fingerprint extras. // THEN the choose lock activity is launched without a bundle contains user id only.
verify(mUi).launchChooseLock(null); ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(mUi).launchChooseLock(bundleArgumentCaptor.capture());
assertBundleContainsUserIdOnly(bundleArgumentCaptor.getValue());
} }
private void compareFingerprintExtras(Bundle actualBundle) { private void compareFingerprintExtras(Bundle actualBundle) {
@@ -175,7 +185,12 @@ public final class SetNewPasswordControllerTest {
actualBundle.getBoolean(EXTRA_KEY_FOR_FINGERPRINT)); actualBundle.getBoolean(EXTRA_KEY_FOR_FINGERPRINT));
assertEquals( assertEquals(
"User id must be equaled to the input one.", "User id must be equaled to the input one.",
CURRENT_UID, CURRENT_USER_ID,
actualBundle.getInt(Intent.EXTRA_USER_ID)); actualBundle.getInt(Intent.EXTRA_USER_ID));
} }
private void assertBundleContainsUserIdOnly(Bundle actualBundle) {
assertThat(actualBundle.size()).isEqualTo(1);
assertThat(actualBundle.getInt(Intent.EXTRA_USER_ID)).isEqualTo(CURRENT_USER_ID);
}
} }