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