Fingerprint Strong auth timeout
Allows PO and DO configure strong auth timeout for fingerprint.
Bug: 31430135
Change-Id: Ie6451d49aa95527adc3720d9a2a0848f58940510
(cherry picked from commit 8f010dd25d18151cc47accc7d853b4f8f7fe8491)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 688876c..6ee8485 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -417,6 +417,14 @@
public static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
/**
+ * Default and maximum timeout in milliseconds after which unlocking with weak auth times out,
+ * i.e. the user has to use a strong authentication method like password, PIN or pattern.
+ *
+ * @hide
+ */
+ public static final long DEFAULT_STRONG_AUTH_TIMEOUT_MS = 72 * 60 * 60 * 1000; // 72h
+
+ /**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
* allows a mobile device management application or NFC programmer application which starts
* managed provisioning to pass data to the management application instance after provisioning.
@@ -2336,6 +2344,78 @@
}
/**
+ * Called by a device/profile owner to set the timeout after which unlocking with secondary, non
+ * strong auth (e.g. fingerprint, trust agents) times out, i.e. the user has to use a strong
+ * authentication method like password, pin or pattern.
+ *
+ * <p>This timeout is used internally to reset the timer to require strong auth again after
+ * specified timeout each time it has been successfully used.
+ *
+ * <p>Fingerprint can also be disabled altogether using {@link #KEYGUARD_DISABLE_FINGERPRINT}.
+ *
+ * <p>Trust agents can also be disabled altogether using {@link #KEYGUARD_DISABLE_TRUST_AGENTS}.
+ *
+ * <p>The calling device admin must be a device or profile owner. If it is not,
+ * a {@link SecurityException} will be thrown.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance returned by
+ * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+ * profile.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param timeoutMs The new timeout, after which the user will have to unlock with strong
+ * authentication method. If the timeout is lower than 1 hour (minimum) or higher than
+ * 72 hours (default and maximum) an {@link IllegalArgumentException} is thrown.
+ *
+ * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws IllegalArgumentException if the timeout is lower than 1 hour (minimum) or higher than
+ * 72 hours (default and maximum)
+ *
+ * @hide
+ */
+ public void setRequiredStrongAuthTimeout(@NonNull ComponentName admin,
+ long timeoutMs) {
+ if (mService != null) {
+ try {
+ mService.setRequiredStrongAuthTimeout(admin, timeoutMs, mParentInstance);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Determine for how long the user will be able to use secondary, non strong auth for
+ * authentication, since last strong method authentication (password, pin or pattern) was used.
+ * After the returned timeout the user is required to use strong authentication method.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
+ * accross all participating admins.
+ * @return The timeout or default timeout if not configured
+ *
+ * @hide
+ */
+ public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin) {
+ return getRequiredStrongAuthTimeout(admin, myUserId());
+ }
+
+ /** @hide per-user version */
+ public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin, @UserIdInt int userId) {
+ if (mService != null) {
+ try {
+ return mService.getRequiredStrongAuthTimeout(admin, userId, mParentInstance);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ }
+
+ /**
* Make the device lock immediately, as if the lock screen timeout has expired at the point of
* this call.
* <p>
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 1036f04..dde1efe 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -82,6 +82,9 @@
long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent);
long getMaximumTimeToLockForUserAndProfiles(int userHandle);
+ void setRequiredStrongAuthTimeout(in ComponentName who, long timeMs, boolean parent);
+ long getRequiredStrongAuthTimeout(in ComponentName who, int userId, boolean parent);
+
void lockNow(boolean parent);
void wipeData(int flags);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index dccb1a9..60d9c39 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -111,12 +111,6 @@
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
- /**
- * Milliseconds after unlocking with fingerprint times out, i.e. the user has to use a
- * strong auth method like password, PIN or pattern.
- */
- private static final long FINGERPRINT_UNLOCK_TIMEOUT_MS = 72 * 60 * 60 * 1000;
-
// Callback messages
private static final int MSG_TIME_UPDATE = 301;
private static final int MSG_BATTERY_UPDATE = 302;
@@ -608,7 +602,10 @@
}
private void scheduleStrongAuthTimeout() {
- long when = SystemClock.elapsedRealtime() + FINGERPRINT_UNLOCK_TIMEOUT_MS;
+ final DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null,
+ sCurrentUser);
Intent intent = new Intent(ACTION_STRONG_AUTH_TIMEOUT);
intent.putExtra(USER_ID, sCurrentUser);
PendingIntent sender = PendingIntent.getBroadcast(mContext,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 777c0b3..6976b28 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -309,6 +309,12 @@
private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
+ /**
+ * Minimum timeout in milliseconds after which unlocking with weak auth times out,
+ * i.e. the user has to use a strong authentication method like password, PIN or pattern.
+ */
+ private static final long MINIMUM_STRONG_AUTH_TIMEOUT_MS = 1 * 60 * 60 * 1000; // 1h
+
final Context mContext;
final Injector mInjector;
final IPackageManager mIPackageManager;
@@ -550,6 +556,7 @@
private static final String TAG_PERMITTED_IMES = "permitted-imes";
private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
+ private static final String TAG_STRONG_AUTH_UNLOCK_TIMEOUT = "strong-auth-unlock-timeout";
private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
@@ -604,6 +611,8 @@
static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
+ long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+
static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
@@ -753,6 +762,11 @@
out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock));
out.endTag(null, TAG_MAX_TIME_TO_UNLOCK);
}
+ if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
+ out.startTag(null, TAG_STRONG_AUTH_UNLOCK_TIMEOUT);
+ out.attribute(null, ATTR_VALUE, Long.toString(strongAuthUnlockTimeout));
+ out.endTag(null, TAG_STRONG_AUTH_UNLOCK_TIMEOUT);
+ }
if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
out.startTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
out.attribute(null, ATTR_VALUE, Integer.toString(maximumFailedPasswordsForWipe));
@@ -967,6 +981,9 @@
} else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
maximumTimeToUnlock = Long.parseLong(
parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_STRONG_AUTH_UNLOCK_TIMEOUT.equals(tag)) {
+ strongAuthUnlockTimeout = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
maximumFailedPasswordsForWipe = Integer.parseInt(
parser.getAttributeValue(null, ATTR_VALUE));
@@ -1218,6 +1235,8 @@
pw.println(minimumPasswordNonLetter);
pw.print(prefix); pw.print("maximumTimeToUnlock=");
pw.println(maximumTimeToUnlock);
+ pw.print(prefix); pw.print("strongAuthUnlockTimeout=");
+ pw.println(strongAuthUnlockTimeout);
pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
pw.println(maximumFailedPasswordsForWipe);
pw.print(prefix); pw.print("specifiesGlobalProxy=");
@@ -4223,6 +4242,60 @@
}
@Override
+ public void setRequiredStrongAuthTimeout(ComponentName who, long timeoutMs,
+ boolean parent) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkArgument(timeoutMs >= MINIMUM_STRONG_AUTH_TIMEOUT_MS,
+ "Timeout must not be lower than the minimum strong auth timeout.");
+ Preconditions.checkArgument(timeoutMs <= DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS,
+ "Timeout must not be higher than the default strong auth timeout.");
+
+ final int userHandle = mInjector.userHandleGetCallingUserId();
+ synchronized (this) {
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ if (ap.strongAuthUnlockTimeout != timeoutMs) {
+ ap.strongAuthUnlockTimeout = timeoutMs;
+ saveSettingsLocked(userHandle);
+ }
+ }
+ }
+
+ /**
+ * Return a single admin's strong auth unlock timeout or minimum value (strictest) of all
+ * admins if who is null.
+ * Returns default timeout if not configured.
+ */
+ @Override
+ public long getRequiredStrongAuthTimeout(ComponentName who, int userId, boolean parent) {
+ if (!mHasFeature) {
+ return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ }
+ enforceFullCrossUsersPermission(userId);
+ synchronized (this) {
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent);
+ return admin != null ? Math.max(admin.strongAuthUnlockTimeout,
+ MINIMUM_STRONG_AUTH_TIMEOUT_MS)
+ : DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ }
+
+ // Return the strictest policy across all participating admins.
+ List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userId, parent);
+
+ long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ for (int i = 0; i < admins.size(); i++) {
+ strongAuthUnlockTimeout = Math.min(admins.get(i).strongAuthUnlockTimeout,
+ strongAuthUnlockTimeout);
+ }
+ return Math.max(strongAuthUnlockTimeout, MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+ }
+ }
+
+ @Override
public void lockNow(boolean parent) {
if (!mHasFeature) {
return;