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