1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.locksettings;
18 
19 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
20 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
21 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
22 
23 import android.app.AlarmManager;
24 import android.app.AlarmManager.OnAlarmListener;
25 import android.app.admin.DevicePolicyManager;
26 import android.app.trust.IStrongAuthTracker;
27 import android.content.Context;
28 import android.os.Handler;
29 import android.os.Looper;
30 import android.os.Message;
31 import android.os.RemoteCallbackList;
32 import android.os.RemoteException;
33 import android.os.SystemClock;
34 import android.os.UserHandle;
35 import android.util.ArrayMap;
36 import android.util.Slog;
37 import android.util.SparseBooleanArray;
38 import android.util.SparseIntArray;
39 
40 import com.android.internal.annotations.VisibleForTesting;
41 import com.android.internal.util.IndentingPrintWriter;
42 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
43 
44 /**
45  * Keeps track of requests for strong authentication.
46  */
47 public class LockSettingsStrongAuth {
48 
49     private static final String TAG = "LockSettings";
50     private static final boolean DEBUG = false;
51 
52     private static final int MSG_REQUIRE_STRONG_AUTH = 1;
53     private static final int MSG_REGISTER_TRACKER = 2;
54     private static final int MSG_UNREGISTER_TRACKER = 3;
55     private static final int MSG_REMOVE_USER = 4;
56     private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5;
57     private static final int MSG_NO_LONGER_REQUIRE_STRONG_AUTH = 6;
58     private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT = 7;
59     private static final int MSG_STRONG_BIOMETRIC_UNLOCK = 8;
60     private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT = 9;
61     private static final int MSG_REFRESH_STRONG_AUTH_TIMEOUT = 10;
62 
63     @VisibleForTesting
64     protected static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
65             "LockSettingsStrongAuth.timeoutForUser";
66     @VisibleForTesting
67     protected static final String NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG =
68             "LockSettingsPrimaryAuth.nonStrongBiometricTimeoutForUser";
69     @VisibleForTesting
70     protected static final String NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG =
71             "LockSettingsPrimaryAuth.nonStrongBiometricIdleTimeoutForUser";
72 
73     /**
74      * Default and maximum timeout in milliseconds after which unlocking with weak auth times out,
75      * i.e. the user has to use a strong authentication method like password, PIN or pattern.
76      */
77     public static final long DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS = 24 * 60 * 60 * 1000; // 24h
78     public static final long DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS =
79             4 * 60 * 60 * 1000; // 4h
80 
81     private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>();
82     @VisibleForTesting
83     protected final SparseIntArray mStrongAuthForUser = new SparseIntArray();
84     @VisibleForTesting
85     protected final SparseBooleanArray mIsNonStrongBiometricAllowedForUser =
86             new SparseBooleanArray();
87     @VisibleForTesting
88     protected final ArrayMap<Integer, StrongAuthTimeoutAlarmListener>
89             mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>();
90     // Track non-strong biometric timeout
91     @VisibleForTesting
92     protected final ArrayMap<Integer, NonStrongBiometricTimeoutAlarmListener>
93             mNonStrongBiometricTimeoutAlarmListener = new ArrayMap<>();
94     // Track non-strong biometric idle timeout
95     @VisibleForTesting
96     protected final ArrayMap<Integer, NonStrongBiometricIdleTimeoutAlarmListener>
97             mNonStrongBiometricIdleTimeoutAlarmListener = new ArrayMap<>();
98 
99     private final int mDefaultStrongAuthFlags;
100     private final boolean mDefaultIsNonStrongBiometricAllowed = true;
101 
102     private final Context mContext;
103     private final Injector mInjector;
104     private final AlarmManager mAlarmManager;
105 
LockSettingsStrongAuth(Context context)106     public LockSettingsStrongAuth(Context context) {
107         this(context, new Injector());
108     }
109 
110     @VisibleForTesting
LockSettingsStrongAuth(Context context, Injector injector)111     protected LockSettingsStrongAuth(Context context, Injector injector) {
112         mContext = context;
113         mInjector = injector;
114         mDefaultStrongAuthFlags = mInjector.getDefaultStrongAuthFlags(context);
115         mAlarmManager = mInjector.getAlarmManager(context);
116     }
117 
118     /**
119      * Class for injecting dependencies into LockSettingsStrongAuth.
120      */
121     @VisibleForTesting
122     public static class Injector {
123 
124         /**
125          * Allows to mock AlarmManager for testing.
126          */
127         @VisibleForTesting
getAlarmManager(Context context)128         public AlarmManager getAlarmManager(Context context) {
129             return context.getSystemService(AlarmManager.class);
130         }
131 
132         /**
133          * Allows to get different default StrongAuthFlags for testing.
134          */
135         @VisibleForTesting
getDefaultStrongAuthFlags(Context context)136         public int getDefaultStrongAuthFlags(Context context) {
137             return StrongAuthTracker.getDefaultFlags(context);
138         }
139 
140         /**
141          * Allows to get different triggerAtMillis values when setting alarms for testing.
142          */
143         @VisibleForTesting
getNextAlarmTimeMs(long timeout)144         public long getNextAlarmTimeMs(long timeout) {
145             return SystemClock.elapsedRealtime() + timeout;
146         }
147 
148         /**
149          * Wraps around {@link SystemClock#elapsedRealtime}, which returns the number of
150          * milliseconds since boot, including time spent in sleep.
151          */
152         @VisibleForTesting
getElapsedRealtimeMs()153         public long getElapsedRealtimeMs() {
154             return SystemClock.elapsedRealtime();
155         }
156     }
157 
handleAddStrongAuthTracker(IStrongAuthTracker tracker)158     private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
159         mTrackers.register(tracker);
160 
161         for (int i = 0; i < mStrongAuthForUser.size(); i++) {
162             int key = mStrongAuthForUser.keyAt(i);
163             int value = mStrongAuthForUser.valueAt(i);
164             try {
165                 tracker.onStrongAuthRequiredChanged(value, key);
166             } catch (RemoteException e) {
167                 Slog.e(TAG, "Exception while adding StrongAuthTracker.", e);
168             }
169         }
170 
171         for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
172             int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
173             boolean value = mIsNonStrongBiometricAllowedForUser.valueAt(i);
174             try {
175                 tracker.onIsNonStrongBiometricAllowedChanged(value, key);
176             } catch (RemoteException e) {
177                 Slog.e(TAG, "Exception while adding StrongAuthTracker: "
178                         + "IsNonStrongBiometricAllowedChanged.", e);
179             }
180         }
181     }
182 
handleRemoveStrongAuthTracker(IStrongAuthTracker tracker)183     private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
184         mTrackers.unregister(tracker);
185     }
186 
handleRequireStrongAuth(int strongAuthReason, int userId)187     private void handleRequireStrongAuth(int strongAuthReason, int userId) {
188         if (userId == UserHandle.USER_ALL) {
189             for (int i = 0; i < mStrongAuthForUser.size(); i++) {
190                 int key = mStrongAuthForUser.keyAt(i);
191                 handleRequireStrongAuthOneUser(strongAuthReason, key);
192             }
193         } else {
194             handleRequireStrongAuthOneUser(strongAuthReason, userId);
195         }
196     }
197 
handleRequireStrongAuthOneUser(int strongAuthReason, int userId)198     private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) {
199         int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags);
200         int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED
201                 ? STRONG_AUTH_NOT_REQUIRED
202                 : (oldValue | strongAuthReason);
203         if (oldValue != newValue) {
204             mStrongAuthForUser.put(userId, newValue);
205             notifyStrongAuthTrackers(newValue, userId);
206         }
207     }
208 
handleNoLongerRequireStrongAuth(int strongAuthReason, int userId)209     private void handleNoLongerRequireStrongAuth(int strongAuthReason, int userId) {
210         if (userId == UserHandle.USER_ALL) {
211             for (int i = 0; i < mStrongAuthForUser.size(); i++) {
212                 int key = mStrongAuthForUser.keyAt(i);
213                 handleNoLongerRequireStrongAuthOneUser(strongAuthReason, key);
214             }
215         } else {
216             handleNoLongerRequireStrongAuthOneUser(strongAuthReason, userId);
217         }
218     }
219 
handleNoLongerRequireStrongAuthOneUser(int strongAuthReason, int userId)220     private void handleNoLongerRequireStrongAuthOneUser(int strongAuthReason, int userId) {
221         int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags);
222         int newValue = oldValue & ~strongAuthReason;
223         if (oldValue != newValue) {
224             mStrongAuthForUser.put(userId, newValue);
225             notifyStrongAuthTrackers(newValue, userId);
226         }
227     }
228 
handleRemoveUser(int userId)229     private void handleRemoveUser(int userId) {
230         int index = mStrongAuthForUser.indexOfKey(userId);
231         if (index >= 0) {
232             mStrongAuthForUser.removeAt(index);
233             notifyStrongAuthTrackers(mDefaultStrongAuthFlags, userId);
234         }
235 
236         index = mIsNonStrongBiometricAllowedForUser.indexOfKey(userId);
237         if (index >= 0) {
238             mIsNonStrongBiometricAllowedForUser.removeAt(index);
239             notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(
240                     mDefaultIsNonStrongBiometricAllowed, userId);
241         }
242     }
243 
244     /**
245      * Re-schedule the strong auth timeout alarm with latest information on the most recent
246      * successful strong auth time and strong auth timeout from device policy.
247      */
rescheduleStrongAuthTimeoutAlarm(long strongAuthTime, int userId)248     private void rescheduleStrongAuthTimeoutAlarm(long strongAuthTime, int userId) {
249         final DevicePolicyManager dpm =
250                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
251         // cancel current alarm listener for the user (if there was one)
252         StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
253         if (alarm != null) {
254             mAlarmManager.cancel(alarm);
255             alarm.setLatestStrongAuthTime(strongAuthTime);
256         } else {
257             alarm = new StrongAuthTimeoutAlarmListener(strongAuthTime, userId);
258             mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
259         }
260         // AlarmManager.set() correctly handles the case where nextAlarmTime has already been in
261         // the past (by firing the listener straight away), so nothing special for us to do here.
262         long nextAlarmTime = strongAuthTime + dpm.getRequiredStrongAuthTimeout(null, userId);
263 
264         // schedule a new alarm listener for the user
265         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
266                 STRONG_AUTH_TIMEOUT_ALARM_TAG, alarm, mHandler);
267     }
268 
handleScheduleStrongAuthTimeout(int userId)269     private void handleScheduleStrongAuthTimeout(int userId) {
270         rescheduleStrongAuthTimeoutAlarm(mInjector.getElapsedRealtimeMs(), userId);
271 
272         // cancel current non-strong biometric alarm listener for the user (if there was one)
273         cancelNonStrongBiometricAlarmListener(userId);
274         // cancel current non-strong biometric idle alarm listener for the user (if there was one)
275         cancelNonStrongBiometricIdleAlarmListener(userId);
276         // re-allow unlock with non-strong biometrics
277         setIsNonStrongBiometricAllowed(true, userId);
278     }
279 
handleRefreshStrongAuthTimeout(int userId)280     private void handleRefreshStrongAuthTimeout(int userId) {
281         StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
282         if (alarm != null) {
283             rescheduleStrongAuthTimeoutAlarm(alarm.getLatestStrongAuthTime(), userId);
284         }
285     }
286 
handleScheduleNonStrongBiometricTimeout(int userId)287     private void handleScheduleNonStrongBiometricTimeout(int userId) {
288         if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricTimeout for userId=" + userId);
289         long nextAlarmTime = mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS);
290         NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
291                 .get(userId);
292         if (alarm != null) {
293             // Unlock with non-strong biometric will not affect the existing non-strong biometric
294             // timeout alarm
295             if (DEBUG) {
296                 Slog.d(TAG, "There is an existing alarm for non-strong biometric"
297                         + " fallback timeout, so do not re-schedule");
298             }
299         } else {
300             if (DEBUG) {
301                 Slog.d(TAG, "Schedule a new alarm for non-strong biometric fallback timeout");
302             }
303             alarm = new NonStrongBiometricTimeoutAlarmListener(userId);
304             mNonStrongBiometricTimeoutAlarmListener.put(userId, alarm);
305             // schedule a new alarm listener for the user
306             mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
307                     NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm, mHandler);
308         }
309 
310         // cancel current non-strong biometric idle alarm listener for the user (if there was one)
311         cancelNonStrongBiometricIdleAlarmListener(userId);
312     }
313 
handleStrongBiometricUnlock(int userId)314     private void handleStrongBiometricUnlock(int userId) {
315         if (DEBUG) Slog.d(TAG, "handleStrongBiometricUnlock for userId=" + userId);
316         // cancel current non-strong biometric alarm listener for the user (if there was one)
317         cancelNonStrongBiometricAlarmListener(userId);
318         // cancel current non-strong biometric idle alarm listener for the user (if there was one)
319         cancelNonStrongBiometricIdleAlarmListener(userId);
320         // re-allow unlock with non-strong biometrics
321         setIsNonStrongBiometricAllowed(true, userId);
322     }
323 
cancelNonStrongBiometricAlarmListener(int userId)324     private void cancelNonStrongBiometricAlarmListener(int userId) {
325         if (DEBUG) Slog.d(TAG, "cancelNonStrongBiometricAlarmListener for userId=" + userId);
326         NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
327                 .get(userId);
328         if (alarm != null) {
329             if (DEBUG) Slog.d(TAG, "Cancel alarm for non-strong biometric fallback timeout");
330             mAlarmManager.cancel(alarm);
331             // need to remove the alarm when cancelled by primary auth or strong biometric
332             mNonStrongBiometricTimeoutAlarmListener.remove(userId);
333         }
334     }
335 
cancelNonStrongBiometricIdleAlarmListener(int userId)336     private void cancelNonStrongBiometricIdleAlarmListener(int userId) {
337         if (DEBUG) Slog.d(TAG, "cancelNonStrongBiometricIdleAlarmListener for userId=" + userId);
338         // cancel idle alarm listener by any unlocks (i.e. primary auth, strong biometric,
339         // non-strong biometric)
340         NonStrongBiometricIdleTimeoutAlarmListener alarm =
341                 mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
342         if (alarm != null) {
343             if (DEBUG) Slog.d(TAG, "Cancel alarm for non-strong biometric idle timeout");
344             mAlarmManager.cancel(alarm);
345         }
346     }
347 
348     @VisibleForTesting
setIsNonStrongBiometricAllowed(boolean allowed, int userId)349     protected void setIsNonStrongBiometricAllowed(boolean allowed, int userId) {
350         if (DEBUG) {
351             Slog.d(TAG, "setIsNonStrongBiometricAllowed for allowed=" + allowed
352                     + ", userId=" + userId);
353         }
354         if (userId == UserHandle.USER_ALL) {
355             for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
356                 int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
357                 setIsNonStrongBiometricAllowedOneUser(allowed, key);
358             }
359         } else {
360             setIsNonStrongBiometricAllowedOneUser(allowed, userId);
361         }
362     }
363 
setIsNonStrongBiometricAllowedOneUser(boolean allowed, int userId)364     private void setIsNonStrongBiometricAllowedOneUser(boolean allowed, int userId) {
365         if (DEBUG) {
366             Slog.d(TAG, "setIsNonStrongBiometricAllowedOneUser for allowed=" + allowed
367                     + ", userId=" + userId);
368         }
369         boolean oldValue = mIsNonStrongBiometricAllowedForUser.get(userId,
370                 mDefaultIsNonStrongBiometricAllowed);
371         if (allowed != oldValue) {
372             if (DEBUG) {
373                 Slog.d(TAG, "mIsNonStrongBiometricAllowedForUser value changed:"
374                         + " oldValue=" + oldValue + ", allowed=" + allowed);
375             }
376             mIsNonStrongBiometricAllowedForUser.put(userId, allowed);
377             notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(allowed, userId);
378         }
379     }
380 
handleScheduleNonStrongBiometricIdleTimeout(int userId)381     private void handleScheduleNonStrongBiometricIdleTimeout(int userId) {
382         if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricIdleTimeout for userId=" + userId);
383         long nextAlarmTime =
384                 mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS);
385         // cancel current alarm listener for the user (if there was one)
386         NonStrongBiometricIdleTimeoutAlarmListener alarm =
387                 mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
388         if (alarm != null) {
389             if (DEBUG) Slog.d(TAG, "Cancel existing alarm for non-strong biometric idle timeout");
390             mAlarmManager.cancel(alarm);
391         } else {
392             alarm = new NonStrongBiometricIdleTimeoutAlarmListener(userId);
393             mNonStrongBiometricIdleTimeoutAlarmListener.put(userId, alarm);
394         }
395         // schedule a new alarm listener for the user
396         if (DEBUG) Slog.d(TAG, "Schedule a new alarm for non-strong biometric idle timeout");
397         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
398                 NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm, mHandler);
399     }
400 
notifyStrongAuthTrackers(int strongAuthReason, int userId)401     private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
402         int i = mTrackers.beginBroadcast();
403         try {
404             while (i > 0) {
405                 i--;
406                 try {
407                     mTrackers.getBroadcastItem(i).onStrongAuthRequiredChanged(
408                             strongAuthReason, userId);
409                 } catch (RemoteException e) {
410                     Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
411                 }
412             }
413         } finally {
414             mTrackers.finishBroadcast();
415         }
416     }
417 
notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(boolean allowed, int userId)418     private void notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(boolean allowed,
419             int userId) {
420         if (DEBUG) {
421             Slog.d(TAG, "notifyStrongAuthTrackersForIsNonStrongBiometricAllowed"
422                     + " for allowed=" + allowed + ", userId=" + userId);
423         }
424         int i = mTrackers.beginBroadcast();
425         try {
426             while (i > 0) {
427                 i--;
428                 try {
429                     mTrackers.getBroadcastItem(i).onIsNonStrongBiometricAllowedChanged(
430                             allowed, userId);
431                 } catch (RemoteException e) {
432                     Slog.e(TAG, "Exception while notifying StrongAuthTracker: "
433                             + "IsNonStrongBiometricAllowedChanged.", e);
434                 }
435             }
436         } finally {
437             mTrackers.finishBroadcast();
438         }
439     }
440 
registerStrongAuthTracker(IStrongAuthTracker tracker)441     public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
442         mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget();
443     }
444 
unregisterStrongAuthTracker(IStrongAuthTracker tracker)445     public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
446         mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget();
447     }
448 
removeUser(int userId)449     public void removeUser(int userId) {
450         final int argNotUsed = 0;
451         mHandler.obtainMessage(MSG_REMOVE_USER, userId, argNotUsed).sendToTarget();
452     }
453 
requireStrongAuth(int strongAuthReason, int userId)454     public void requireStrongAuth(int strongAuthReason, int userId) {
455         if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) {
456             mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason,
457                     userId).sendToTarget();
458         } else {
459             throw new IllegalArgumentException(
460                     "userId must be an explicit user id or USER_ALL");
461         }
462     }
463 
noLongerRequireStrongAuth(int strongAuthReason, int userId)464     void noLongerRequireStrongAuth(int strongAuthReason, int userId) {
465         if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) {
466             mHandler.obtainMessage(MSG_NO_LONGER_REQUIRE_STRONG_AUTH, strongAuthReason,
467                     userId).sendToTarget();
468         } else {
469             throw new IllegalArgumentException(
470                     "userId must be an explicit user id or USER_ALL");
471         }
472     }
473 
reportUnlock(int userId)474     public void reportUnlock(int userId) {
475         requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
476     }
477 
478     /**
479      * Report successful unlocking with primary auth
480      */
reportSuccessfulStrongAuthUnlock(int userId)481     public void reportSuccessfulStrongAuthUnlock(int userId) {
482         final int argNotUsed = 0;
483         mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget();
484     }
485 
486     /**
487      * Refreshes pending strong auth timeout with the latest admin requirement set by device policy.
488      */
refreshStrongAuthTimeout(int userId)489     public void refreshStrongAuthTimeout(int userId) {
490         mHandler.obtainMessage(MSG_REFRESH_STRONG_AUTH_TIMEOUT, userId, 0).sendToTarget();
491     }
492 
493     /**
494      * Report successful unlocking with biometric
495      */
reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId)496     public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
497         if (DEBUG) {
498             Slog.d(TAG, "reportSuccessfulBiometricUnlock for isStrongBiometric="
499                     + isStrongBiometric + ", userId=" + userId);
500         }
501         final int argNotUsed = 0;
502         if (isStrongBiometric) { // unlock with strong biometric
503             mHandler.obtainMessage(MSG_STRONG_BIOMETRIC_UNLOCK, userId, argNotUsed)
504                     .sendToTarget();
505         } else { // unlock with non-strong biometric (i.e. weak or convenience)
506             mHandler.obtainMessage(MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT, userId, argNotUsed)
507                     .sendToTarget();
508         }
509     }
510 
511     /**
512      * Schedule idle timeout for non-strong biometric (i.e. weak or convenience)
513      */
scheduleNonStrongBiometricIdleTimeout(int userId)514     public void scheduleNonStrongBiometricIdleTimeout(int userId) {
515         if (DEBUG) Slog.d(TAG, "scheduleNonStrongBiometricIdleTimeout for userId=" + userId);
516         final int argNotUsed = 0;
517         mHandler.obtainMessage(MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT, userId, argNotUsed)
518                 .sendToTarget();
519     }
520 
521     /**
522      * Alarm of fallback timeout for primary auth
523      */
524     @VisibleForTesting
525     protected class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
526 
527         private long mLatestStrongAuthTime;
528         private final int mUserId;
529 
StrongAuthTimeoutAlarmListener(long latestStrongAuthTime, int userId)530         public StrongAuthTimeoutAlarmListener(long latestStrongAuthTime, int userId) {
531             mLatestStrongAuthTime = latestStrongAuthTime;
532             mUserId = userId;
533         }
534 
535         /**
536          * Sets the most recent time when a successful strong auth happened, in number of
537          * milliseconds.
538          */
setLatestStrongAuthTime(long strongAuthTime)539         public void setLatestStrongAuthTime(long strongAuthTime) {
540             mLatestStrongAuthTime = strongAuthTime;
541         }
542 
543         /**
544          * Returns the most recent time when a successful strong auth happened, in number of
545          * milliseconds.
546          */
getLatestStrongAuthTime()547         public long getLatestStrongAuthTime() {
548             return mLatestStrongAuthTime;
549         }
550 
551         @Override
onAlarm()552         public void onAlarm() {
553             requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, mUserId);
554         }
555     }
556 
557     /**
558      * Alarm of fallback timeout for non-strong biometric (i.e. weak or convenience)
559      */
560     @VisibleForTesting
561     protected class NonStrongBiometricTimeoutAlarmListener implements OnAlarmListener {
562 
563         private final int mUserId;
564 
NonStrongBiometricTimeoutAlarmListener(int userId)565         NonStrongBiometricTimeoutAlarmListener(int userId) {
566             mUserId = userId;
567         }
568 
569         @Override
onAlarm()570         public void onAlarm() {
571             requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT, mUserId);
572         }
573     }
574 
575     /**
576      * Alarm of idle timeout for non-strong biometric (i.e. weak or convenience biometric)
577      */
578     @VisibleForTesting
579     protected class NonStrongBiometricIdleTimeoutAlarmListener implements OnAlarmListener {
580 
581         private final int mUserId;
582 
NonStrongBiometricIdleTimeoutAlarmListener(int userId)583         NonStrongBiometricIdleTimeoutAlarmListener(int userId) {
584             mUserId = userId;
585         }
586 
587         @Override
onAlarm()588         public void onAlarm() {
589             // disallow unlock with non-strong biometrics
590             setIsNonStrongBiometricAllowed(false, mUserId);
591         }
592     }
593 
594     @VisibleForTesting
595     protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
596         @Override
597         public void handleMessage(Message msg) {
598             switch (msg.what) {
599                 case MSG_REGISTER_TRACKER:
600                     handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj);
601                     break;
602                 case MSG_UNREGISTER_TRACKER:
603                     handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj);
604                     break;
605                 case MSG_REQUIRE_STRONG_AUTH:
606                     handleRequireStrongAuth(msg.arg1, msg.arg2);
607                     break;
608                 case MSG_REMOVE_USER:
609                     handleRemoveUser(msg.arg1);
610                     break;
611                 case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT:
612                     handleScheduleStrongAuthTimeout(msg.arg1);
613                     break;
614                 case MSG_REFRESH_STRONG_AUTH_TIMEOUT:
615                     handleRefreshStrongAuthTimeout(msg.arg1);
616                     break;
617                 case MSG_NO_LONGER_REQUIRE_STRONG_AUTH:
618                     handleNoLongerRequireStrongAuth(msg.arg1, msg.arg2);
619                     break;
620                 case MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT:
621                     handleScheduleNonStrongBiometricTimeout(msg.arg1);
622                     break;
623                 case MSG_STRONG_BIOMETRIC_UNLOCK:
624                     handleStrongBiometricUnlock(msg.arg1);
625                     break;
626                 case MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT:
627                     handleScheduleNonStrongBiometricIdleTimeout(msg.arg1);
628                     break;
629             }
630         }
631     };
632 
dump(IndentingPrintWriter pw)633     public void dump(IndentingPrintWriter pw) {
634         pw.println("PrimaryAuthFlags state:");
635         pw.increaseIndent();
636         for (int i = 0; i < mStrongAuthForUser.size(); i++) {
637             final int key = mStrongAuthForUser.keyAt(i);
638             final int value = mStrongAuthForUser.valueAt(i);
639             pw.println("userId=" + key + ", primaryAuthFlags=" + Integer.toHexString(value));
640         }
641         pw.println();
642         pw.decreaseIndent();
643 
644         pw.println("NonStrongBiometricAllowed state:");
645         pw.increaseIndent();
646         for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
647             final int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
648             final boolean value = mIsNonStrongBiometricAllowedForUser.valueAt(i);
649             pw.println("userId=" + key + ", allowed=" + value);
650         }
651         pw.println();
652         pw.decreaseIndent();
653     }
654 }
655