Loading core/java/android/app/admin/DevicePolicyManager.java +80 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,14 @@ public class DevicePolicyManager { */ 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 Loading Loading @@ -2335,6 +2343,78 @@ public class DevicePolicyManager { return 0; } /** * 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. Loading core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,9 @@ interface IDevicePolicyManager { 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); Loading packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +4 −7 Original line number Diff line number Diff line Loading @@ -111,12 +111,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { 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; Loading Loading @@ -608,7 +602,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } 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, Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +73 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; Loading Loading @@ -550,6 +556,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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"; Loading Loading @@ -604,6 +611,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; Loading Loading @@ -753,6 +762,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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)); Loading Loading @@ -967,6 +981,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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)); Loading Loading @@ -1218,6 +1235,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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="); Loading Loading @@ -4222,6 +4241,60 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return time; } @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) { Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +80 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,14 @@ public class DevicePolicyManager { */ 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 Loading Loading @@ -2335,6 +2343,78 @@ public class DevicePolicyManager { return 0; } /** * 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. Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,9 @@ interface IDevicePolicyManager { 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); Loading
packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +4 −7 Original line number Diff line number Diff line Loading @@ -111,12 +111,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { 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; Loading Loading @@ -608,7 +602,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } 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, Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +73 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; Loading Loading @@ -550,6 +556,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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"; Loading Loading @@ -604,6 +611,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; Loading Loading @@ -753,6 +762,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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)); Loading Loading @@ -967,6 +981,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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)); Loading Loading @@ -1218,6 +1235,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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="); Loading Loading @@ -4222,6 +4241,60 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return time; } @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) { Loading