blob: a25accd4732c913df2dd66cc3f3f7c2e0e2251d7 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2008 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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080018
Jorim Jaggiccdfa932015-04-13 16:29:48 -070019import android.app.ActivityManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070020import android.app.ActivityManagerNative;
Jorim Jaggic7dea6e2014-07-26 14:36:57 +020021import android.app.AlarmManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070022import android.app.IUserSwitchObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070023import android.app.PendingIntent;
Jim Millerb0304762012-03-13 20:01:25 -070024import android.app.admin.DevicePolicyManager;
Adrian Roos46842d92014-03-27 14:58:03 +010025import android.app.trust.TrustManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080026import android.content.BroadcastReceiver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080030import android.database.ContentObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070031import android.graphics.Bitmap;
Jorim Jaggi86bed402015-08-20 18:20:02 -070032import android.hardware.fingerprint.FingerprintManager;
33import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
34import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
Jim Miller47088bb2009-11-24 00:40:16 -080035import android.media.AudioManager;
Jim Miller79a444a2011-02-15 15:02:11 -080036import android.os.BatteryManager;
Jim Miller9f0753f2015-03-23 23:59:22 -070037import android.os.CancellationSignal;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080038import android.os.Handler;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070039import android.os.IRemoteCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080040import android.os.Message;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070041import android.os.RemoteException;
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -070042import android.os.SystemClock;
Amith Yamasanie8e93a12013-05-09 18:12:30 -070043import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080044import android.provider.Settings;
Etan Cohen47051d82015-07-06 16:19:04 -070045import android.telephony.ServiceState;
Jim Miller52a61332014-11-12 19:29:51 -080046import android.telephony.SubscriptionInfo;
Jim Miller52a61332014-11-12 19:29:51 -080047import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080048import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Jim Millerc23024d2010-02-24 15:37:00 -080049import android.telephony.TelephonyManager;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070050import android.util.ArraySet;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080051import android.util.Log;
Adrian Roos46842d92014-03-27 14:58:03 +010052import android.util.SparseBooleanArray;
Jorim Jaggi9f743032015-05-04 15:22:40 -070053import android.util.SparseIntArray;
Adrian Roos46842d92014-03-27 14:58:03 +010054
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080055import com.google.android.collect.Lists;
56
Jorim Jaggi86bed402015-08-20 18:20:02 -070057import com.android.internal.telephony.IccCardConstants;
58import com.android.internal.telephony.IccCardConstants.State;
59import com.android.internal.telephony.PhoneConstants;
60import com.android.internal.telephony.TelephonyIntents;
Adrian Roosb5e47222015-08-14 15:53:06 -070061import com.android.internal.widget.LockPatternUtils;
Jorim Jaggi86bed402015-08-20 18:20:02 -070062
Jason Monkab525272015-07-13 17:02:49 -040063import java.io.FileDescriptor;
64import java.io.PrintWriter;
Jim Millerdcb3d842012-08-23 19:18:12 -070065import java.lang.ref.WeakReference;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080066import java.util.ArrayList;
Jim Miller52a61332014-11-12 19:29:51 -080067import java.util.HashMap;
68import java.util.List;
69import java.util.Map.Entry;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080070
Jorim Jaggi86bed402015-08-20 18:20:02 -070071import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
72import static android.os.BatteryManager.BATTERY_STATUS_FULL;
73import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
74import static android.os.BatteryManager.EXTRA_HEALTH;
75import static android.os.BatteryManager.EXTRA_LEVEL;
76import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
77import static android.os.BatteryManager.EXTRA_PLUGGED;
78import static android.os.BatteryManager.EXTRA_STATUS;
79
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080080/**
81 * Watches for updates that may be interesting to the keyguard, and provides
82 * the up to date information as well as a registration for callbacks that care
83 * to be updated.
84 *
85 * Note: under time crunch, this has been extended to include some stuff that
86 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
Jim Miller258341c2012-08-30 16:50:10 -070087 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
88 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080089 */
Adrian Roos46842d92014-03-27 14:58:03 +010090public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080091
Jim Millerbbf1a742012-07-17 18:30:30 -070092 private static final String TAG = "KeyguardUpdateMonitor";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010093 private static final boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller52a61332014-11-12 19:29:51 -080094 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
Jim Millerbbf1a742012-07-17 18:30:30 -070095 private static final int LOW_BATTERY_THRESHOLD = 20;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096
Jorim Jaggie7b12522014-08-06 16:41:21 +020097 private static final String ACTION_FACE_UNLOCK_STARTED
98 = "com.android.facelock.FACE_UNLOCK_STARTED";
99 private static final String ACTION_FACE_UNLOCK_STOPPED
100 = "com.android.facelock.FACE_UNLOCK_STOPPED";
101
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700102 private static final String ACTION_STRONG_AUTH_TIMEOUT =
103 "com.android.systemui.ACTION_STRONG_AUTH_TIMEOUT";
104 private static final String USER_ID = "com.android.systemui.USER_ID";
105
106 private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
107
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700108 /**
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700109 * Milliseconds after unlocking with fingerprint times out, i.e. the user has to use a
110 * strong auth method like password, PIN or pattern.
111 */
112 private static final long FINGERPRINT_UNLOCK_TIMEOUT_MS = 72 * 60 * 60 * 1000;
113
Jim Millerbbf1a742012-07-17 18:30:30 -0700114 // Callback messages
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800115 private static final int MSG_TIME_UPDATE = 301;
116 private static final int MSG_BATTERY_UPDATE = 302;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800117 private static final int MSG_SIM_STATE_CHANGE = 304;
Jim Miller47088bb2009-11-24 00:40:16 -0800118 private static final int MSG_RINGER_MODE_CHANGED = 305;
Jim Millerc23024d2010-02-24 15:37:00 -0800119 private static final int MSG_PHONE_STATE_CHANGED = 306;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700120 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -0700121 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500122 private static final int MSG_USER_SWITCHING = 310;
Selim Cinek1fcafc42015-07-20 14:39:25 -0700123 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 311;
124 private static final int MSG_KEYGUARD_RESET = 312;
Jim Millerf41fc962014-06-18 16:33:51 -0700125 private static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500126 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Millerf41fc962014-06-18 16:33:51 -0700127 private static final int MSG_USER_INFO_CHANGED = 317;
128 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700129 private static final int MSG_STARTED_WAKING_UP = 319;
130 private static final int MSG_FINISHED_GOING_TO_SLEEP = 320;
Adrian Roosb6011622014-05-14 15:52:53 +0200131 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700132 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327;
133 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
Jason Monk052082c2015-06-11 11:35:23 -0400134 private static final int MSG_AIRPLANE_MODE_CHANGED = 329;
Etan Cohen47051d82015-07-06 16:19:04 -0700135 private static final int MSG_SERVICE_STATE_CHANGE = 330;
Jorim Jaggif1518da2015-07-30 11:56:36 -0700136 private static final int MSG_SCREEN_TURNED_ON = 331;
137 private static final int MSG_SCREEN_TURNED_OFF = 332;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800138
Jorim Jaggi86bed402015-08-20 18:20:02 -0700139 /** Fingerprint state: Not listening to fingerprint. */
140 private static final int FINGERPRINT_STATE_STOPPED = 0;
141
142 /** Fingerprint state: Listening. */
143 private static final int FINGERPRINT_STATE_RUNNING = 1;
144
145 /**
146 * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to
147 * send us the confirmation that cancellation has happened.
148 */
149 private static final int FINGERPRINT_STATE_CANCELLING = 2;
150
151 /**
152 * Fingerprint state: During cancelling we got another request to start listening, so when we
153 * receive the cancellation done signal, we should start listening again.
154 */
155 private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3;
156
Jim Millerdcb3d842012-08-23 19:18:12 -0700157 private static KeyguardUpdateMonitor sInstance;
158
Jim Millerbbf1a742012-07-17 18:30:30 -0700159 private final Context mContext;
Jim Miller52a61332014-11-12 19:29:51 -0800160 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
Etan Cohen47051d82015-07-06 16:19:04 -0700161 HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
Jim Millerbbf1a742012-07-17 18:30:30 -0700162
Jim Millerbbf1a742012-07-17 18:30:30 -0700163 private int mRingMode;
164 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400165 private boolean mKeyguardIsVisible;
Jorim Jaggi71448a72015-08-18 19:49:04 -0700166
167 /**
168 * If true, fingerprint was already authenticated and we don't need to start listening again
169 * until the Keyguard has been dismissed.
170 */
171 private boolean mFingerprintAlreadyAuthenticated;
Adrian Roosb6011622014-05-14 15:52:53 +0200172 private boolean mBouncer;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800173 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700174
Jim Millerdcb3d842012-08-23 19:18:12 -0700175 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700176 private boolean mDeviceProvisioned;
177
Jim Millerdcb3d842012-08-23 19:18:12 -0700178 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700179 private BatteryStatus mBatteryStatus;
180
Jim Millerdcb3d842012-08-23 19:18:12 -0700181 // Password attempts
Jorim Jaggi9f743032015-05-04 15:22:40 -0700182 private SparseIntArray mFailedAttempts = new SparseIntArray();
Brian Colonnacc4104f2012-10-09 17:50:46 -0400183
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700184 /** Tracks whether strong authentication hasn't been used since quite some time per user. */
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700185 private ArraySet<Integer> mStrongAuthNotTimedOut = new ArraySet<>();
Adrian Roosb5e47222015-08-14 15:53:06 -0700186 private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker();
Jim Millerbbf1a742012-07-17 18:30:30 -0700187
Jim Miller6212cc02012-09-05 17:35:31 -0700188 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700189 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800190 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700191
Brian Colonnaa5239892013-04-15 11:45:40 -0400192 private boolean mSwitchingUser;
193
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700194 private boolean mDeviceInteractive;
Jim Miller20daffd2013-10-07 14:59:53 -0700195 private boolean mScreenOn;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800196 private SubscriptionManager mSubscriptionManager;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700197 private AlarmManager mAlarmManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800198 private List<SubscriptionInfo> mSubscriptionInfo;
Jorim Jaggi237b0612015-05-01 14:28:49 -0700199 private TrustManager mTrustManager;
Jorim Jaggi86bed402015-08-20 18:20:02 -0700200 private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
Jim Miller20daffd2013-10-07 14:59:53 -0700201
Jim Millerbbf1a742012-07-17 18:30:30 -0700202 private final Handler mHandler = new Handler() {
203 @Override
204 public void handleMessage(Message msg) {
205 switch (msg.what) {
206 case MSG_TIME_UPDATE:
207 handleTimeUpdate();
208 break;
209 case MSG_BATTERY_UPDATE:
210 handleBatteryUpdate((BatteryStatus) msg.obj);
211 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700212 case MSG_SIM_STATE_CHANGE:
Jim Miller52a61332014-11-12 19:29:51 -0800213 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700214 break;
215 case MSG_RINGER_MODE_CHANGED:
216 handleRingerModeChange(msg.arg1);
217 break;
218 case MSG_PHONE_STATE_CHANGED:
Adrian Roosb6011622014-05-14 15:52:53 +0200219 handlePhoneStateChanged((String) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700220 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700221 case MSG_DEVICE_PROVISIONED:
222 handleDeviceProvisioned();
223 break;
224 case MSG_DPM_STATE_CHANGED:
225 handleDevicePolicyManagerStateChanged();
226 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500227 case MSG_USER_SWITCHING:
Adrian Roosb6011622014-05-14 15:52:53 +0200228 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
Chris Wrenf41c61b2012-11-29 15:19:54 -0500229 break;
230 case MSG_USER_SWITCH_COMPLETE:
231 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700232 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400233 case MSG_KEYGUARD_VISIBILITY_CHANGED:
234 handleKeyguardVisibilityChanged(msg.arg1);
235 break;
Selim Cinek1fcafc42015-07-20 14:39:25 -0700236 case MSG_KEYGUARD_RESET:
237 handleKeyguardReset();
238 break;
Adrian Roosb6011622014-05-14 15:52:53 +0200239 case MSG_KEYGUARD_BOUNCER_CHANGED:
240 handleKeyguardBouncerChanged(msg.arg1);
241 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800242 case MSG_BOOT_COMPLETED:
243 handleBootCompleted();
244 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700245 case MSG_USER_INFO_CHANGED:
246 handleUserInfoChanged(msg.arg1);
247 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400248 case MSG_REPORT_EMERGENCY_CALL_ACTION:
249 handleReportEmergencyCallAction();
250 break;
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700251 case MSG_FINISHED_GOING_TO_SLEEP:
252 handleFinishedGoingToSleep(msg.arg1);
Jim Miller20daffd2013-10-07 14:59:53 -0700253 break;
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700254 case MSG_STARTED_WAKING_UP:
255 handleStartedWakingUp();
Jim Miller20daffd2013-10-07 14:59:53 -0700256 break;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200257 case MSG_FACE_UNLOCK_STATE_CHANGED:
Adrian Roos4a410172014-08-20 17:41:44 +0200258 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200259 break;
Jim Miller52a61332014-11-12 19:29:51 -0800260 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED:
261 handleSimSubscriptionInfoChanged();
262 break;
Jason Monk052082c2015-06-11 11:35:23 -0400263 case MSG_AIRPLANE_MODE_CHANGED:
264 handleAirplaneModeChanged();
265 break;
Etan Cohen47051d82015-07-06 16:19:04 -0700266 case MSG_SERVICE_STATE_CHANGE:
267 handleServiceStateChange(msg.arg1, (ServiceState) msg.obj);
268 break;
Jorim Jaggif1518da2015-07-30 11:56:36 -0700269 case MSG_SCREEN_TURNED_ON:
270 handleScreenTurnedOn();
271 break;
272 case MSG_SCREEN_TURNED_OFF:
273 handleScreenTurnedOff();
274 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700275 }
276 }
277 };
278
Wink Savilled09c4ca2014-11-22 10:08:16 -0800279 private OnSubscriptionsChangedListener mSubscriptionListener =
280 new OnSubscriptionsChangedListener() {
Jim Miller52a61332014-11-12 19:29:51 -0800281 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800282 public void onSubscriptionsChanged() {
Jim Miller52a61332014-11-12 19:29:51 -0800283 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
284 }
285 };
286
Adrian Roos46842d92014-03-27 14:58:03 +0100287 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
Adrian Roos7861c662014-07-25 15:37:28 +0200288 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
Jim Miller9f0753f2015-03-23 23:59:22 -0700289 private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
Adrian Roos4a410172014-08-20 17:41:44 +0200290 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
Adrian Roos46842d92014-03-27 14:58:03 +0100291
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700292 private static int sCurrentUser;
293
294 public synchronized static void setCurrentUser(int currentUser) {
295 sCurrentUser = currentUser;
296 }
297
298 public synchronized static int getCurrentUser() {
299 return sCurrentUser;
300 }
301
Adrian Roos46842d92014-03-27 14:58:03 +0100302 @Override
Adrian Roos94e15a52015-04-16 12:23:18 -0700303 public void onTrustChanged(boolean enabled, int userId, int flags) {
Adrian Roos46842d92014-03-27 14:58:03 +0100304 mUserHasTrust.put(userId, enabled);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200305 for (int i = 0; i < mCallbacks.size(); i++) {
306 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
307 if (cb != null) {
308 cb.onTrustChanged(userId);
Adrian Roos94e15a52015-04-16 12:23:18 -0700309 if (enabled && flags != 0) {
310 cb.onTrustGrantedWithFlags(flags, userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200311 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200312 }
313 }
Adrian Roos46842d92014-03-27 14:58:03 +0100314 }
315
Jim Miller52a61332014-11-12 19:29:51 -0800316 protected void handleSimSubscriptionInfoChanged() {
317 if (DEBUG_SIM_STATES) {
318 Log.v(TAG, "onSubscriptionInfoChanged()");
Wink Savilled09c4ca2014-11-22 10:08:16 -0800319 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
320 if (sil != null) {
321 for (SubscriptionInfo subInfo : sil) {
322 Log.v(TAG, "SubInfo:" + subInfo);
323 }
324 } else {
325 Log.v(TAG, "onSubscriptionInfoChanged: list is null");
Jim Miller52a61332014-11-12 19:29:51 -0800326 }
327 }
328 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
329
330 // Hack level over 9000: Because the subscription id is not yet valid when we see the
331 // first update in handleSimStateChange, we need to force refresh all all SIM states
332 // so the subscription id for them is consistent.
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100333 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
Jim Miller52a61332014-11-12 19:29:51 -0800334 for (int i = 0; i < subscriptionInfos.size(); i++) {
335 SubscriptionInfo info = subscriptionInfos.get(i);
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100336 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
337 if (changed) {
338 changedSubscriptions.add(info);
339 }
Jim Miller52a61332014-11-12 19:29:51 -0800340 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100341 for (int i = 0; i < changedSubscriptions.size(); i++) {
342 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
Jim Miller52a61332014-11-12 19:29:51 -0800343 for (int j = 0; j < mCallbacks.size(); j++) {
344 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
345 if (cb != null) {
346 cb.onSimStateChanged(data.subId, data.slotId, data.simState);
347 }
348 }
349 }
Jason Monk6c985dc2015-01-09 16:07:14 -0500350 for (int j = 0; j < mCallbacks.size(); j++) {
351 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
352 if (cb != null) {
353 cb.onRefreshCarrierInfo();
354 }
355 }
Jim Miller52a61332014-11-12 19:29:51 -0800356 }
357
Jason Monk052082c2015-06-11 11:35:23 -0400358 private void handleAirplaneModeChanged() {
359 for (int j = 0; j < mCallbacks.size(); j++) {
360 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
361 if (cb != null) {
362 cb.onRefreshCarrierInfo();
363 }
364 }
365 }
366
Wink Savilled09c4ca2014-11-22 10:08:16 -0800367 /** @return List of SubscriptionInfo records, maybe empty but never null */
Jim Miller52a61332014-11-12 19:29:51 -0800368 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
Wink Savilled09c4ca2014-11-22 10:08:16 -0800369 List<SubscriptionInfo> sil = mSubscriptionInfo;
370 if (sil == null || forceReload) {
371 sil = mSubscriptionManager.getActiveSubscriptionInfoList();
372 }
373 if (sil == null) {
374 // getActiveSubscriptionInfoList was null callers expect an empty list.
375 mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
376 } else {
377 mSubscriptionInfo = sil;
Jim Miller52a61332014-11-12 19:29:51 -0800378 }
379 return mSubscriptionInfo;
380 }
381
Adrian Roos7861c662014-07-25 15:37:28 +0200382 @Override
383 public void onTrustManagedChanged(boolean managed, int userId) {
384 mUserTrustIsManaged.put(userId, managed);
385
386 for (int i = 0; i < mCallbacks.size(); i++) {
387 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
388 if (cb != null) {
389 cb.onTrustManagedChanged(userId);
390 }
391 }
392 }
393
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700394 private void onFingerprintAuthenticated(int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700395 mUserFingerprintAuthenticated.put(userId, true);
Jorim Jaggi71448a72015-08-18 19:49:04 -0700396
397 // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
398 // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
399 // fully gone.
400 mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
Jim Millerf41fc962014-06-18 16:33:51 -0700401 for (int i = 0; i < mCallbacks.size(); i++) {
402 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
403 if (cb != null) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700404 cb.onFingerprintAuthenticated(userId);
Jim Millerf41fc962014-06-18 16:33:51 -0700405 }
406 }
407 }
408
Jim Millerce7eb6d2015-04-03 19:29:13 -0700409 private void handleFingerprintAuthFailed() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700410 for (int i = 0; i < mCallbacks.size(); i++) {
411 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
412 if (cb != null) {
413 cb.onFingerprintAuthFailed();
414 }
Jorim Jaggi007f0e82015-08-14 13:56:01 -0700415 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700416 handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
417 }
Jim Millerf41fc962014-06-18 16:33:51 -0700418
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700419 private void handleFingerprintAcquired(int acquireInfo) {
420 if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
421 return;
422 }
Jorim Jaggi007f0e82015-08-14 13:56:01 -0700423 for (int i = 0; i < mCallbacks.size(); i++) {
424 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
425 if (cb != null) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700426 cb.onFingerprintAcquired();
Jorim Jaggi007f0e82015-08-14 13:56:01 -0700427 }
428 }
429 }
430
Jim Miller4f364c92015-06-08 19:24:13 -0700431 private void handleFingerprintAuthenticated() {
Jim Millerf41fc962014-06-18 16:33:51 -0700432 try {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700433 final int userId;
434 try {
435 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
436 } catch (RemoteException e) {
437 Log.e(TAG, "Failed to get current user id: ", e);
438 return;
Jim Millerf41fc962014-06-18 16:33:51 -0700439 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700440 if (isFingerprintDisabled(userId)) {
441 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
442 return;
443 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700444 onFingerprintAuthenticated(userId);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700445 } finally {
Jorim Jaggi86bed402015-08-20 18:20:02 -0700446 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
Jim Millerf41fc962014-06-18 16:33:51 -0700447 }
448 }
449
Jim Miller9f0753f2015-03-23 23:59:22 -0700450 private void handleFingerprintHelp(int msgId, String helpString) {
Jim Millerf41fc962014-06-18 16:33:51 -0700451 for (int i = 0; i < mCallbacks.size(); i++) {
452 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
453 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700454 cb.onFingerprintHelp(msgId, helpString);
455 }
456 }
457 }
458
459 private void handleFingerprintError(int msgId, String errString) {
Jorim Jaggi86bed402015-08-20 18:20:02 -0700460 if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
461 && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
462 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
463 startListeningForFingerprint();
464 } else {
465 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
466 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700467 for (int i = 0; i < mCallbacks.size(); i++) {
468 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
469 if (cb != null) {
470 cb.onFingerprintError(msgId, errString);
Jim Millerf41fc962014-06-18 16:33:51 -0700471 }
472 }
473 }
474
Jorim Jaggi86bed402015-08-20 18:20:02 -0700475 private void setFingerprintRunningState(int fingerprintRunningState) {
476 boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
477 boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
478 mFingerprintRunningState = fingerprintRunningState;
479
480 // Clients of KeyguardUpdateMonitor don't care about the internal state about the
481 // asynchronousness of the cancel cycle. So only notify them if the actualy running state
482 // has changed.
483 if (wasRunning != isRunning) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700484 notifyFingerprintRunningStateChanged();
485 }
486 }
487
488 private void notifyFingerprintRunningStateChanged() {
489 for (int i = 0; i < mCallbacks.size(); i++) {
490 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
491 if (cb != null) {
Jorim Jaggi86bed402015-08-20 18:20:02 -0700492 cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning());
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700493 }
494 }
495 }
Adrian Roos4a410172014-08-20 17:41:44 +0200496 private void handleFaceUnlockStateChanged(boolean running, int userId) {
497 mUserFaceUnlockRunning.put(userId, running);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200498 for (int i = 0; i < mCallbacks.size(); i++) {
499 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
500 if (cb != null) {
Adrian Roos4a410172014-08-20 17:41:44 +0200501 cb.onFaceUnlockStateChanged(running, userId);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200502 }
503 }
504 }
505
Adrian Roos4a410172014-08-20 17:41:44 +0200506 public boolean isFaceUnlockRunning(int userId) {
507 return mUserFaceUnlockRunning.get(userId);
508 }
509
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700510 public boolean isFingerprintDetectionRunning() {
Jorim Jaggi86bed402015-08-20 18:20:02 -0700511 return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700512 }
513
Jim Miller50e62182014-04-23 17:25:00 -0700514 private boolean isTrustDisabled(int userId) {
Adrian Roosa4da9f62015-02-21 01:15:21 +0100515 // Don't allow trust agent if device is secured with a SIM PIN. This is here
516 // mainly because there's no other way to prompt the user to enter their SIM PIN
517 // once they get past the keyguard screen.
518 final boolean disabledBySimPin = isSimPinSecure();
519 return disabledBySimPin;
Jim Miller50e62182014-04-23 17:25:00 -0700520 }
521
Jim Miller06e34502014-07-17 14:46:05 -0700522 private boolean isFingerprintDisabled(int userId) {
523 final DevicePolicyManager dpm =
524 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
525 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
Adrian Roos733b6632015-08-21 14:32:35 -0700526 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0
527 || isSimPinSecure();
Jim Miller06e34502014-07-17 14:46:05 -0700528 }
529
Selim Cineke8bae622015-07-15 13:24:06 -0700530 public boolean getUserCanSkipBouncer(int userId) {
Selim Cinek1fcafc42015-07-20 14:39:25 -0700531 return getUserHasTrust(userId) || (mUserFingerprintAuthenticated.get(userId)
532 && isUnlockingWithFingerprintAllowed());
Selim Cineke8bae622015-07-15 13:24:06 -0700533 }
534
Adrian Roos46842d92014-03-27 14:58:03 +0100535 public boolean getUserHasTrust(int userId) {
Selim Cineke8bae622015-07-15 13:24:06 -0700536 return !isTrustDisabled(userId) && mUserHasTrust.get(userId);
Adrian Roos46842d92014-03-27 14:58:03 +0100537 }
538
Adrian Roos7861c662014-07-25 15:37:28 +0200539 public boolean getUserTrustIsManaged(int userId) {
540 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
541 }
542
Selim Cinek1fcafc42015-07-20 14:39:25 -0700543 public boolean isUnlockingWithFingerprintAllowed() {
Adrian Roosb5e47222015-08-14 15:53:06 -0700544 return mStrongAuthTracker.isUnlockingWithFingerprintAllowed()
545 && !hasFingerprintUnlockTimedOut(sCurrentUser);
546 }
547
548 public StrongAuthTracker getStrongAuthTracker() {
549 return mStrongAuthTracker;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700550 }
551
552 /**
553 * @return true if the user hasn't use strong authentication (pattern, PIN, password) since a
554 * while and thus can't unlock with fingerprint, false otherwise
555 */
556 public boolean hasFingerprintUnlockTimedOut(int userId) {
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700557 return !mStrongAuthNotTimedOut.contains(userId);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700558 }
559
560 public void reportSuccessfulStrongAuthUnlockAttempt() {
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700561 mStrongAuthNotTimedOut.add(sCurrentUser);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700562 scheduleStrongAuthTimeout();
Jim Millere0507bb2015-08-12 20:30:34 -0700563 if (mFpm != null) {
564 byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
565 mFpm.resetTimeout(token);
566 }
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700567 }
568
569 private void scheduleStrongAuthTimeout() {
570 long when = SystemClock.elapsedRealtime() + FINGERPRINT_UNLOCK_TIMEOUT_MS;
571 Intent intent = new Intent(ACTION_STRONG_AUTH_TIMEOUT);
572 intent.putExtra(USER_ID, sCurrentUser);
573 PendingIntent sender = PendingIntent.getBroadcast(mContext,
574 sCurrentUser, intent, PendingIntent.FLAG_CANCEL_CURRENT);
575 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, sender);
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700576 notifyStrongAuthStateChanged(sCurrentUser);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700577 }
578
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700579 private void notifyStrongAuthStateChanged(int userId) {
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700580 for (int i = 0; i < mCallbacks.size(); i++) {
581 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
582 if (cb != null) {
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700583 cb.onStrongAuthStateChanged(userId);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700584 }
585 }
Selim Cinek1fcafc42015-07-20 14:39:25 -0700586 }
587
Jim Miller8f09fd22013-03-14 19:04:28 -0700588 static class DisplayClientState {
589 public int clientGeneration;
590 public boolean clearing;
591 public PendingIntent intent;
592 public int playbackState;
593 public long playbackEventTime;
594 }
595
596 private DisplayClientState mDisplayClientState = new DisplayClientState();
597
Jim Millerbbf1a742012-07-17 18:30:30 -0700598 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
599
600 public void onReceive(Context context, Intent intent) {
601 final String action = intent.getAction();
602 if (DEBUG) Log.d(TAG, "received broadcast " + action);
603
604 if (Intent.ACTION_TIME_TICK.equals(action)
605 || Intent.ACTION_TIME_CHANGED.equals(action)
Adrian Roos48c796c2014-09-01 14:59:23 +0200606 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700607 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700608 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
609 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
610 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
611 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
612 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
Adrian Roos7b043112015-07-10 13:00:33 -0700613 final int maxChargingCurrent = intent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT, -1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700614 final Message msg = mHandler.obtainMessage(
Adrian Roos7b043112015-07-10 13:00:33 -0700615 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health,
616 maxChargingCurrent));
Jim Millerbbf1a742012-07-17 18:30:30 -0700617 mHandler.sendMessage(msg);
618 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller52a61332014-11-12 19:29:51 -0800619 SimData args = SimData.fromIntent(intent);
Jim Millerbbf1a742012-07-17 18:30:30 -0700620 if (DEBUG_SIM_STATES) {
Jim Miller52a61332014-11-12 19:29:51 -0800621 Log.v(TAG, "action " + action
622 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
623 + " slotId: " + args.slotId + " subid: " + args.subId);
Jim Millerbbf1a742012-07-17 18:30:30 -0700624 }
Jim Miller52a61332014-11-12 19:29:51 -0800625 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
626 .sendToTarget();
Jim Millerbbf1a742012-07-17 18:30:30 -0700627 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
628 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
629 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
630 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
631 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
632 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
Jason Monk052082c2015-06-11 11:35:23 -0400633 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
634 mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED);
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800635 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700636 dispatchBootCompleted();
Etan Cohen47051d82015-07-06 16:19:04 -0700637 } else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
638 ServiceState serviceState = ServiceState.newFromBundle(intent.getExtras());
639 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
640 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
641 if (DEBUG) {
642 Log.v(TAG, "action " + action + " serviceState=" + serviceState + " subId="
643 + subId);
644 }
645 mHandler.sendMessage(
646 mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
Jim Millerbbf1a742012-07-17 18:30:30 -0700647 }
648 }
649 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700650
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700651 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
652
653 public void onReceive(Context context, Intent intent) {
654 final String action = intent.getAction();
Adrian Roos48c796c2014-09-01 14:59:23 +0200655 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
656 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
657 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700658 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
659 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
Adrian Roos48c796c2014-09-01 14:59:23 +0200660 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
661 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
662 getSendingUserId()));
663 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
664 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
665 getSendingUserId()));
666 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
667 .equals(action)) {
668 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700669 }
670 }
671 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700672
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700673 private final BroadcastReceiver mStrongAuthTimeoutReceiver = new BroadcastReceiver() {
674 @Override
675 public void onReceive(Context context, Intent intent) {
676 if (ACTION_STRONG_AUTH_TIMEOUT.equals(intent.getAction())) {
677 int userId = intent.getIntExtra(USER_ID, -1);
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700678 mStrongAuthNotTimedOut.remove(userId);
679 notifyStrongAuthStateChanged(userId);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700680 }
681 }
682 };
683
Jim Miller9f0753f2015-03-23 23:59:22 -0700684 private FingerprintManager.AuthenticationCallback mAuthenticationCallback
685 = new AuthenticationCallback() {
Jim Millerf41fc962014-06-18 16:33:51 -0700686
687 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700688 public void onAuthenticationFailed() {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700689 handleFingerprintAuthFailed();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700690 };
691
692 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700693 public void onAuthenticationSucceeded(AuthenticationResult result) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700694 handleFingerprintAuthenticated();
Jim Millerf41fc962014-06-18 16:33:51 -0700695 }
696
697 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700698 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700699 handleFingerprintHelp(helpMsgId, helpString.toString());
Jim Miller9f0753f2015-03-23 23:59:22 -0700700 }
701
702 @Override
703 public void onAuthenticationError(int errMsgId, CharSequence errString) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700704 handleFingerprintError(errMsgId, errString.toString());
705 }
706
707 @Override
708 public void onAuthenticationAcquired(int acquireInfo) {
709 handleFingerprintAcquired(acquireInfo);
Jim Millerf41fc962014-06-18 16:33:51 -0700710 }
711 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700712 private CancellationSignal mFingerprintCancelSignal;
713 private FingerprintManager mFpm;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700714
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800715 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800716 * When we receive a
717 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700718 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800719 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800720 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800721 */
Jim Miller52a61332014-11-12 19:29:51 -0800722 private static class SimData {
723 public State simState;
724 public int slotId;
725 public int subId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800726
Jim Miller52a61332014-11-12 19:29:51 -0800727 SimData(State state, int slot, int id) {
Jim Miller90d5d462011-11-17 16:57:01 -0800728 simState = state;
Jim Miller52a61332014-11-12 19:29:51 -0800729 slotId = slot;
730 subId = id;
Jim Miller90d5d462011-11-17 16:57:01 -0800731 }
732
Jim Miller52a61332014-11-12 19:29:51 -0800733 static SimData fromIntent(Intent intent) {
734 State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800735 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
736 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
737 }
Wink Savillea639b312012-07-10 12:37:54 -0700738 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
Jim Miller52a61332014-11-12 19:29:51 -0800739 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
740 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
Wink Savilled09c4ca2014-11-22 10:08:16 -0800741 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea639b312012-07-10 12:37:54 -0700742 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700743 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700744 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700745
Wink Savillea639b312012-07-10 12:37:54 -0700746 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700747 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700748 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700749 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700750 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700751 }
Wink Savillea639b312012-07-10 12:37:54 -0700752 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
753 state = IccCardConstants.State.READY;
754 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800755 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700756 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
757 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
758 state = IccCardConstants.State.PIN_REQUIRED;
759 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
760 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800761 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700762 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800763 }
Wink Savillea639b312012-07-10 12:37:54 -0700764 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
765 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700766 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
767 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
768 // This is required because telephony doesn't return to "READY" after
769 // these state transitions. See bug 7197471.
770 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800771 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700772 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800773 }
Jim Miller52a61332014-11-12 19:29:51 -0800774 return new SimData(state, slotId, subId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800775 }
776
777 public String toString() {
Jim Miller52a61332014-11-12 19:29:51 -0800778 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800779 }
780 }
781
Adrian Roos12c1ef52014-06-04 13:54:08 +0200782 public static class BatteryStatus {
Adrian Roos7b043112015-07-10 13:00:33 -0700783 public static final int CHARGING_UNKNOWN = -1;
784 public static final int CHARGING_SLOWLY = 0;
785 public static final int CHARGING_REGULAR = 1;
786 public static final int CHARGING_FAST = 2;
787
Jim Miller16464b82011-10-20 21:10:13 -0700788 public final int status;
789 public final int level;
790 public final int plugged;
791 public final int health;
Adrian Roos7b043112015-07-10 13:00:33 -0700792 public final int maxChargingCurrent;
793 public BatteryStatus(int status, int level, int plugged, int health, int maxChargingCurrent) {
Jim Miller16464b82011-10-20 21:10:13 -0700794 this.status = status;
795 this.level = level;
796 this.plugged = plugged;
797 this.health = health;
Adrian Roos7b043112015-07-10 13:00:33 -0700798 this.maxChargingCurrent = maxChargingCurrent;
Jim Miller16464b82011-10-20 21:10:13 -0700799 }
800
Jim Millerbbf1a742012-07-17 18:30:30 -0700801 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700802 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700803 * @return true if the device is plugged in.
804 */
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100805 public boolean isPluggedIn() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700806 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700807 || plugged == BatteryManager.BATTERY_PLUGGED_USB
808 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700809 }
810
811 /**
812 * Whether or not the device is charged. Note that some devices never return 100% for
813 * battery level, so this allows either battery level or status to determine if the
814 * battery is charged.
815 * @return true if the device is charged
816 */
817 public boolean isCharged() {
818 return status == BATTERY_STATUS_FULL || level >= 100;
819 }
820
821 /**
822 * Whether battery is low and needs to be charged.
823 * @return true if battery is low
824 */
825 public boolean isBatteryLow() {
826 return level < LOW_BATTERY_THRESHOLD;
827 }
828
Adrian Roos7b043112015-07-10 13:00:33 -0700829 public final int getChargingSpeed(int slowThreshold, int fastThreshold) {
830 return maxChargingCurrent <= 0 ? CHARGING_UNKNOWN :
831 maxChargingCurrent < slowThreshold ? CHARGING_SLOWLY :
832 maxChargingCurrent > fastThreshold ? CHARGING_FAST :
833 CHARGING_REGULAR;
834 }
Jim Miller16464b82011-10-20 21:10:13 -0700835 }
836
Adrian Roosb5e47222015-08-14 15:53:06 -0700837 public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
838
839 public boolean isUnlockingWithFingerprintAllowed() {
840 int userId = getCurrentUser();
841 return isFingerprintAllowedForUser(userId);
842 }
843
844 public boolean hasUserAuthenticatedSinceBoot() {
845 int userId = getCurrentUser();
846 return (getStrongAuthForUser(userId)
847 & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0;
848 }
849
850 @Override
851 public void onStrongAuthRequiredChanged(int userId) {
Adrian Roos1de8bcb2015-08-19 16:52:52 -0700852 notifyStrongAuthStateChanged(userId);
Adrian Roosb5e47222015-08-14 15:53:06 -0700853 }
854 }
855
Jim Millerdcb3d842012-08-23 19:18:12 -0700856 public static KeyguardUpdateMonitor getInstance(Context context) {
857 if (sInstance == null) {
858 sInstance = new KeyguardUpdateMonitor(context);
859 }
860 return sInstance;
861 }
862
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700863 protected void handleStartedWakingUp() {
Jorim Jaggi864e64b2015-05-20 14:13:23 -0700864 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700865 final int count = mCallbacks.size();
866 for (int i = 0; i < count; i++) {
867 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
868 if (cb != null) {
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700869 cb.onStartedWakingUp();
Jim Miller20daffd2013-10-07 14:59:53 -0700870 }
871 }
872 }
873
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700874 protected void handleFinishedGoingToSleep(int arg1) {
Jim Millerf41fc962014-06-18 16:33:51 -0700875 clearFingerprintRecognized();
Jim Miller20daffd2013-10-07 14:59:53 -0700876 final int count = mCallbacks.size();
877 for (int i = 0; i < count; i++) {
878 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
879 if (cb != null) {
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700880 cb.onFinishedGoingToSleep(arg1);
Jim Miller20daffd2013-10-07 14:59:53 -0700881 }
882 }
Jorim Jaggi71448a72015-08-18 19:49:04 -0700883 mFingerprintAlreadyAuthenticated = false;
Jorim Jaggiea657062015-04-28 13:45:11 -0700884 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700885 }
886
Jorim Jaggif1518da2015-07-30 11:56:36 -0700887 private void handleScreenTurnedOn() {
888 final int count = mCallbacks.size();
889 for (int i = 0; i < count; i++) {
890 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
891 if (cb != null) {
892 cb.onScreenTurnedOn();
893 }
894 }
895 }
896
897 private void handleScreenTurnedOff() {
898 final int count = mCallbacks.size();
899 for (int i = 0; i < count; i++) {
900 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
901 if (cb != null) {
902 cb.onScreenTurnedOff();
903 }
904 }
905 }
906
Adam Powell43a372f2013-09-27 17:43:53 -0700907 /**
908 * IMPORTANT: Must be called from UI thread.
909 */
910 public void dispatchSetBackground(Bitmap bmp) {
911 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
912 final int count = mCallbacks.size();
913 for (int i = 0; i < count; i++) {
914 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
915 if (cb != null) {
916 cb.onSetBackground(bmp);
917 }
918 }
919 }
920
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700921 private void handleUserInfoChanged(int userId) {
922 for (int i = 0; i < mCallbacks.size(); i++) {
923 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
924 if (cb != null) {
925 cb.onUserInfoChanged(userId);
926 }
927 }
928 }
929
Jim Millerdcb3d842012-08-23 19:18:12 -0700930 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800931 mContext = context;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800932 mSubscriptionManager = SubscriptionManager.from(context);
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700933 mAlarmManager = context.getSystemService(AlarmManager.class);
Michael Jurkafff56142012-11-28 16:51:00 -0800934 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700935
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800936 // Since device can't be un-provisioned, we only need to register a content observer
937 // to update mDeviceProvisioned when we are...
938 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700939 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800940 }
Jim Miller47088bb2009-11-24 00:40:16 -0800941
Jim Millerbbf1a742012-07-17 18:30:30 -0700942 // Take a guess at initial SIM state, battery status and PLMN until we get an update
Adrian Roos7b043112015-07-10 13:00:33 -0700943 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800944
Jim Millerbbf1a742012-07-17 18:30:30 -0700945 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800946 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800947 filter.addAction(Intent.ACTION_TIME_TICK);
948 filter.addAction(Intent.ACTION_TIME_CHANGED);
949 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
950 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
Jason Monk052082c2015-06-11 11:35:23 -0400951 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800952 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Etan Cohen47051d82015-07-06 16:19:04 -0700953 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800954 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Jim Miller47088bb2009-11-24 00:40:16 -0800955 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerbbf1a742012-07-17 18:30:30 -0700956 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700957
Adam Cohenc276e822012-11-08 13:01:08 -0800958 final IntentFilter bootCompleteFilter = new IntentFilter();
959 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
960 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
961 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
962
Adrian Roos48c796c2014-09-01 14:59:23 +0200963 final IntentFilter allUserFilter = new IntentFilter();
964 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
965 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
966 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
967 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
968 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
969 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700970 null, null);
971
Wink Saville071743f2015-01-12 17:11:04 -0800972 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700973 try {
974 ActivityManagerNative.getDefault().registerUserSwitchObserver(
975 new IUserSwitchObserver.Stub() {
976 @Override
977 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500978 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700979 newUserId, 0, reply));
980 }
981 @Override
982 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500983 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
Adrian Roosbe47b072014-09-03 00:08:56 +0200984 newUserId, 0));
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700985 }
Kenny Guy42979622015-04-13 18:03:05 +0000986 @Override
987 public void onForegroundProfileSwitch(int newProfileId) {
988 // Ignore.
989 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700990 });
991 } catch (RemoteException e) {
992 // TODO Auto-generated catch block
993 e.printStackTrace();
994 }
Adrian Roos46842d92014-03-27 14:58:03 +0100995
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700996 IntentFilter strongAuthTimeoutFilter = new IntentFilter();
997 strongAuthTimeoutFilter.addAction(ACTION_STRONG_AUTH_TIMEOUT);
998 context.registerReceiver(mStrongAuthTimeoutReceiver, strongAuthTimeoutFilter,
999 PERMISSION_SELF, null /* handler */);
Jorim Jaggi237b0612015-05-01 14:28:49 -07001000 mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
1001 mTrustManager.registerTrustListener(this);
Adrian Roosb5e47222015-08-14 15:53:06 -07001002 new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker);
Jim Millerf41fc962014-06-18 16:33:51 -07001003
Jim Miller9f0753f2015-03-23 23:59:22 -07001004 mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
Jorim Jaggiea657062015-04-28 13:45:11 -07001005 updateFingerprintListeningState();
1006 }
1007
1008 private void updateFingerprintListeningState() {
1009 boolean shouldListenForFingerprint = shouldListenForFingerprint();
Jorim Jaggi86bed402015-08-20 18:20:02 -07001010 if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
Jorim Jaggiea657062015-04-28 13:45:11 -07001011 stopListeningForFingerprint();
Jorim Jaggi86bed402015-08-20 18:20:02 -07001012 } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
1013 && shouldListenForFingerprint) {
Jorim Jaggiea657062015-04-28 13:45:11 -07001014 startListeningForFingerprint();
1015 }
1016 }
1017
1018 private boolean shouldListenForFingerprint() {
Jorim Jaggi71448a72015-08-18 19:49:04 -07001019 return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser
Adrian Roos733b6632015-08-21 14:32:35 -07001020 && !mFingerprintAlreadyAuthenticated && !isFingerprintDisabled(getCurrentUser());
Jim Miller9f0753f2015-03-23 23:59:22 -07001021 }
1022
Jim Millerce7eb6d2015-04-03 19:29:13 -07001023 private void startListeningForFingerprint() {
Jorim Jaggi86bed402015-08-20 18:20:02 -07001024 if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
1025 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
1026 return;
1027 }
Jim Millerce7eb6d2015-04-03 19:29:13 -07001028 if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -07001029 int userId = ActivityManager.getCurrentUser();
Jorim Jaggi71448a72015-08-18 19:49:04 -07001030 if (isUnlockWithFingerprintPossible(userId)) {
Jim Millerce7eb6d2015-04-03 19:29:13 -07001031 if (mFingerprintCancelSignal != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -07001032 mFingerprintCancelSignal.cancel();
1033 }
Jim Millerce7eb6d2015-04-03 19:29:13 -07001034 mFingerprintCancelSignal = new CancellationSignal();
Jim Millerf501b582015-06-03 16:36:31 -07001035 mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
Jorim Jaggi86bed402015-08-20 18:20:02 -07001036 setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
Jim Miller9f0753f2015-03-23 23:59:22 -07001037 }
1038 }
1039
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -07001040 public boolean isUnlockWithFingerprintPossible(int userId) {
Selim Cinek3122fa82015-06-18 01:38:59 -07001041 return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
1042 && mFpm.getEnrolledFingerprints(userId).size() > 0;
1043 }
1044
Jorim Jaggiea657062015-04-28 13:45:11 -07001045 private void stopListeningForFingerprint() {
Jim Millerce7eb6d2015-04-03 19:29:13 -07001046 if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
Jorim Jaggi86bed402015-08-20 18:20:02 -07001047 if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) {
Jim Miller9f0753f2015-03-23 23:59:22 -07001048 mFingerprintCancelSignal.cancel();
Jim Millerce7eb6d2015-04-03 19:29:13 -07001049 mFingerprintCancelSignal = null;
Jorim Jaggi86bed402015-08-20 18:20:02 -07001050 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
Jim Miller9f0753f2015-03-23 23:59:22 -07001051 }
Jorim Jaggi86bed402015-08-20 18:20:02 -07001052 if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
1053 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
1054 }
Jim Millerbbf1a742012-07-17 18:30:30 -07001055 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001056
Michael Jurkafff56142012-11-28 16:51:00 -08001057 private boolean isDeviceProvisionedInSettingsDb() {
1058 return Settings.Global.getInt(mContext.getContentResolver(),
1059 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1060 }
1061
Jim Millerbbf1a742012-07-17 18:30:30 -07001062 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -08001063 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001064 @Override
1065 public void onChange(boolean selfChange) {
1066 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -08001067 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -07001068 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -07001069 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001070 }
Jim Millerbbf1a742012-07-17 18:30:30 -07001071 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001072 }
Jim Millerbbf1a742012-07-17 18:30:30 -07001073 };
1074
1075 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -07001076 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -08001077 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -07001078
1079 // prevent a race condition between where we check the flag and where we register the
1080 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -08001081 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -07001082 if (provisioned != mDeviceProvisioned) {
1083 mDeviceProvisioned = provisioned;
1084 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -07001085 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -07001086 }
1087 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001088 }
1089
Jim Millerbbf1a742012-07-17 18:30:30 -07001090 /**
1091 * Handle {@link #MSG_DPM_STATE_CHANGED}
1092 */
Jim Millerb0304762012-03-13 20:01:25 -07001093 protected void handleDevicePolicyManagerStateChanged() {
Adrian Roos733b6632015-08-21 14:32:35 -07001094 updateFingerprintListeningState();
Jim Millerdcb3d842012-08-23 19:18:12 -07001095 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1096 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1097 if (cb != null) {
1098 cb.onDevicePolicyManagerStateChanged();
1099 }
Jim Millerb0304762012-03-13 20:01:25 -07001100 }
1101 }
1102
Jim Millerbbf1a742012-07-17 18:30:30 -07001103 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -05001104 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -07001105 */
Chris Wrenf41c61b2012-11-29 15:19:54 -05001106 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001107 mSwitchingUser = true;
1108 updateFingerprintListeningState();
1109
Jim Millerbbf1a742012-07-17 18:30:30 -07001110 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001111 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1112 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -05001113 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -07001114 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07001115 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001116 try {
1117 reply.sendResult(null);
1118 } catch (RemoteException e) {
1119 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07001120 }
1121
Jim Millerbbf1a742012-07-17 18:30:30 -07001122 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -05001123 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
1124 */
1125 protected void handleUserSwitchComplete(int userId) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001126 mSwitchingUser = false;
1127 updateFingerprintListeningState();
1128
Chris Wrenf41c61b2012-11-29 15:19:54 -05001129 for (int i = 0; i < mCallbacks.size(); i++) {
1130 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1131 if (cb != null) {
1132 cb.onUserSwitchComplete(userId);
1133 }
1134 }
1135 }
1136
1137 /**
Jim Miller90873d52013-09-26 18:11:38 -07001138 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
1139 * keyguard crashes sometime after boot, then it will never receive this
1140 * broadcast and hence not handle the event. This method is ultimately called by
1141 * PhoneWindowManager in this case.
1142 */
Jorim Jaggi5cf17872014-03-26 18:31:48 +01001143 public void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -07001144 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -07001145 }
1146
1147 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -08001148 * Handle {@link #MSG_BOOT_COMPLETED}
1149 */
1150 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -07001151 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -08001152 mBootCompleted = true;
Adam Cohenefb3ffb2012-11-06 16:55:32 -08001153 for (int i = 0; i < mCallbacks.size(); i++) {
1154 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1155 if (cb != null) {
1156 cb.onBootCompleted();
1157 }
1158 }
1159 }
1160
1161 /**
Jim Miller5ecd8112013-01-09 18:50:26 -08001162 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -08001163 * destroyed.
1164 */
1165 public boolean hasBootCompleted() {
1166 return mBootCompleted;
1167 }
1168
1169 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001170 * Handle {@link #MSG_DEVICE_PROVISIONED}
1171 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -07001172 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -07001173 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001174 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1175 if (cb != null) {
1176 cb.onDeviceProvisioned();
1177 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -07001178 }
Michael Jurkafff56142012-11-28 16:51:00 -08001179 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -07001180 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -08001181 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
1182 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -07001183 }
1184 }
1185
Jim Millerbbf1a742012-07-17 18:30:30 -07001186 /**
1187 * Handle {@link #MSG_PHONE_STATE_CHANGED}
1188 */
Jim Millerc23024d2010-02-24 15:37:00 -08001189 protected void handlePhoneStateChanged(String newState) {
1190 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -07001191 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
1192 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
1193 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
1194 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
1195 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
1196 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
1197 }
Jim Millerbbf1a742012-07-17 18:30:30 -07001198 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001199 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1200 if (cb != null) {
1201 cb.onPhoneStateChanged(mPhoneState);
1202 }
Jim Millerc23024d2010-02-24 15:37:00 -08001203 }
1204 }
1205
Jim Millerbbf1a742012-07-17 18:30:30 -07001206 /**
1207 * Handle {@link #MSG_RINGER_MODE_CHANGED}
1208 */
Jim Miller47088bb2009-11-24 00:40:16 -08001209 protected void handleRingerModeChange(int mode) {
1210 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -07001211 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -07001212 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001213 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1214 if (cb != null) {
1215 cb.onRingerModeChanged(mode);
1216 }
Jim Miller47088bb2009-11-24 00:40:16 -08001217 }
1218 }
1219
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001220 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001221 * Handle {@link #MSG_TIME_UPDATE}
1222 */
1223 private void handleTimeUpdate() {
1224 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -07001225 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001226 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1227 if (cb != null) {
1228 cb.onTimeChanged();
1229 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001230 }
1231 }
1232
1233 /**
1234 * Handle {@link #MSG_BATTERY_UPDATE}
1235 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001236 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001237 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -07001238 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
1239 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -07001240 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001241 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001242 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1243 if (cb != null) {
1244 cb.onRefreshBatteryInfo(status);
1245 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001246 }
1247 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001248 }
1249
1250 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001251 * Handle {@link #MSG_SIM_STATE_CHANGE}
1252 */
Jim Miller52a61332014-11-12 19:29:51 -08001253 private void handleSimStateChange(int subId, int slotId, State state) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001254
Jim Miller52a61332014-11-12 19:29:51 -08001255 if (DEBUG_SIM_STATES) {
1256 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
1257 + slotId + ", state=" + state +")");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001258 }
1259
Wink Savillea54bf652014-12-11 13:37:50 -08001260 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Jim Miller52a61332014-11-12 19:29:51 -08001261 Log.w(TAG, "invalid subId in handleSimStateChange()");
1262 return;
1263 }
1264
1265 SimData data = mSimDatas.get(subId);
1266 final boolean changed;
1267 if (data == null) {
1268 data = new SimData(state, slotId, subId);
1269 mSimDatas.put(subId, data);
1270 changed = true; // no data yet; force update
1271 } else {
1272 changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
1273 data.simState = state;
1274 data.subId = subId;
1275 data.slotId = slotId;
1276 }
1277 if (changed && state != State.UNKNOWN) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001278 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001279 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1280 if (cb != null) {
Jim Miller52a61332014-11-12 19:29:51 -08001281 cb.onSimStateChanged(subId, slotId, state);
Jim Millerdcb3d842012-08-23 19:18:12 -07001282 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001283 }
1284 }
1285 }
1286
Jim Millerbbf1a742012-07-17 18:30:30 -07001287 /**
Etan Cohen47051d82015-07-06 16:19:04 -07001288 * Handle {@link #MSG_SERVICE_STATE_CHANGE}
1289 */
1290 private void handleServiceStateChange(int subId, ServiceState serviceState) {
1291 if (DEBUG) {
1292 Log.d(TAG,
1293 "handleServiceStateChange(subId=" + subId + ", serviceState=" + serviceState);
1294 }
1295
1296 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1297 Log.w(TAG, "invalid subId in handleServiceStateChange()");
1298 return;
1299 }
1300
1301 mServiceStates.put(subId, serviceState);
1302
1303 for (int j = 0; j < mCallbacks.size(); j++) {
1304 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
1305 if (cb != null) {
1306 cb.onRefreshCarrierInfo();
1307 }
1308 }
1309 }
1310
1311 /**
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001312 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
1313 */
1314 private void handleKeyguardVisibilityChanged(int showing) {
1315 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -04001316 boolean isShowing = (showing == 1);
1317 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001318 for (int i = 0; i < mCallbacks.size(); i++) {
1319 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1320 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -04001321 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001322 }
1323 }
Jorim Jaggi71448a72015-08-18 19:49:04 -07001324 if (!isShowing) {
1325 mFingerprintAlreadyAuthenticated = false;
1326 }
Jorim Jaggiea657062015-04-28 13:45:11 -07001327 updateFingerprintListeningState();
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001328 }
1329
Brian Colonna7fce3802013-09-17 15:51:32 -04001330 /**
Selim Cinek1fcafc42015-07-20 14:39:25 -07001331 * Handle {@link #MSG_KEYGUARD_RESET}
1332 */
1333 private void handleKeyguardReset() {
1334 if (DEBUG) Log.d(TAG, "handleKeyguardReset");
Adrian Roosf6d51ac2015-09-02 13:26:25 -07001335 updateFingerprintListeningState();
Selim Cinek1fcafc42015-07-20 14:39:25 -07001336 }
1337
1338 /**
Adrian Roosb6011622014-05-14 15:52:53 +02001339 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
1340 * @see #sendKeyguardBouncerChanged(boolean)
1341 */
1342 private void handleKeyguardBouncerChanged(int bouncer) {
1343 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
1344 boolean isBouncer = (bouncer == 1);
1345 mBouncer = isBouncer;
1346 for (int i = 0; i < mCallbacks.size(); i++) {
1347 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1348 if (cb != null) {
1349 cb.onKeyguardBouncerChanged(isBouncer);
1350 }
1351 }
1352 }
1353
1354 /**
Brian Colonna7fce3802013-09-17 15:51:32 -04001355 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
1356 */
1357 private void handleReportEmergencyCallAction() {
1358 for (int i = 0; i < mCallbacks.size(); i++) {
1359 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1360 if (cb != null) {
1361 cb.onEmergencyCallAction();
1362 }
1363 }
1364 }
1365
Jim Miller16464b82011-10-20 21:10:13 -07001366 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001367 final boolean nowPluggedIn = current.isPluggedIn();
1368 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -08001369 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -07001370 wasPluggedIn == true && nowPluggedIn == true
1371 && (old.status != current.status);
1372
1373 // change in plug state is always interesting
1374 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001375 return true;
1376 }
1377
1378 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -07001379 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001380 return true;
1381 }
1382
Jim Miller16464b82011-10-20 21:10:13 -07001383 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -07001384 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -07001385 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001386 }
Adrian Roos76dc5a52015-07-21 16:20:36 -07001387
1388 // change in charging current while plugged in
1389 if (nowPluggedIn && current.maxChargingCurrent != old.maxChargingCurrent) {
1390 return true;
1391 }
1392
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001393 return false;
1394 }
1395
1396 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001397 * Remove the given observer's callback.
1398 *
Jim Miller6212cc02012-09-05 17:35:31 -07001399 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001400 */
Jim Miller6212cc02012-09-05 17:35:31 -07001401 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1402 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1403 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1404 if (mCallbacks.get(i).get() == callback) {
1405 mCallbacks.remove(i);
1406 }
1407 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001408 }
1409
1410 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001411 * Register to receive notifications about general keyguard information
1412 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -07001413 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001414 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001415 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -07001416 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1417 // Prevent adding duplicate callbacks
1418 for (int i = 0; i < mCallbacks.size(); i++) {
1419 if (mCallbacks.get(i).get() == callback) {
1420 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1421 new Exception("Called by"));
1422 return;
Jim Millerdcb3d842012-08-23 19:18:12 -07001423 }
1424 }
Jim Miller6212cc02012-09-05 17:35:31 -07001425 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1426 removeCallback(null); // remove unused references
1427 sendUpdates(callback);
1428 }
1429
1430 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1431 // Notify listener of the current state
1432 callback.onRefreshBatteryInfo(mBatteryStatus);
1433 callback.onTimeChanged();
1434 callback.onRingerModeChanged(mRingMode);
1435 callback.onPhoneStateChanged(mPhoneState);
Jason Monk9ff69bd2014-12-02 16:43:17 -05001436 callback.onRefreshCarrierInfo();
Jim Miller6212cc02012-09-05 17:35:31 -07001437 callback.onClockVisibilityChanged();
Jim Miller52a61332014-11-12 19:29:51 -08001438 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
1439 final SimData state = data.getValue();
1440 callback.onSimStateChanged(state.subId, state.slotId, state.simState);
1441 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001442 }
1443
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001444 public void sendKeyguardVisibilityChanged(boolean showing) {
1445 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1446 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1447 message.arg1 = showing ? 1 : 0;
1448 message.sendToTarget();
1449 }
1450
Selim Cinek1fcafc42015-07-20 14:39:25 -07001451 public void sendKeyguardReset() {
1452 mHandler.obtainMessage(MSG_KEYGUARD_RESET).sendToTarget();
1453 }
1454
Adrian Roosb6011622014-05-14 15:52:53 +02001455 /**
1456 * @see #handleKeyguardBouncerChanged(int)
1457 */
1458 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1459 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1460 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1461 message.arg1 = showingBouncer ? 1 : 0;
1462 message.sendToTarget();
1463 }
1464
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001465 /**
Jim Miller90d5d462011-11-17 16:57:01 -08001466 * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001467 * have the information earlier than waiting for the intent
1468 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -08001469 *
1470 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1471 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001472 */
Jim Miller52a61332014-11-12 19:29:51 -08001473 public void reportSimUnlocked(int subId) {
1474 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
1475 int slotId = SubscriptionManager.getSlotId(subId);
1476 handleSimStateChange(subId, slotId, State.READY);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001477 }
1478
Brian Colonna7fce3802013-09-17 15:51:32 -04001479 /**
1480 * Report that the emergency call button has been pressed and the emergency dialer is
1481 * about to be displayed.
1482 *
1483 * @param bypassHandler runs immediately.
1484 *
1485 * NOTE: Must be called from UI thread if bypassHandler == true.
1486 */
1487 public void reportEmergencyCallAction(boolean bypassHandler) {
1488 if (!bypassHandler) {
1489 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1490 } else {
1491 handleReportEmergencyCallAction();
1492 }
1493 }
1494
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001495 /**
1496 * @return Whether the device is provisioned (whether they have gone through
1497 * the setup wizard)
1498 */
1499 public boolean isDeviceProvisioned() {
1500 return mDeviceProvisioned;
1501 }
1502
Jorim Jaggi9f743032015-05-04 15:22:40 -07001503 public void clearFailedUnlockAttempts() {
1504 mFailedAttempts.delete(sCurrentUser);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001505 }
1506
Jorim Jaggi9f743032015-05-04 15:22:40 -07001507 public int getFailedUnlockAttempts() {
1508 return mFailedAttempts.get(sCurrentUser, 0);
1509 }
1510
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -07001511 public void reportFailedStrongAuthUnlockAttempt() {
Jorim Jaggi9f743032015-05-04 15:22:40 -07001512 mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001513 }
1514
Jim Millerf41fc962014-06-18 16:33:51 -07001515 public void clearFingerprintRecognized() {
Jim Miller9f0753f2015-03-23 23:59:22 -07001516 mUserFingerprintAuthenticated.clear();
Jim Millerf41fc962014-06-18 16:33:51 -07001517 }
1518
Jim Miller52a61332014-11-12 19:29:51 -08001519 public boolean isSimPinVoiceSecure() {
1520 // TODO: only count SIMs that handle voice
1521 return isSimPinSecure();
Jim Millerdcb3d842012-08-23 19:18:12 -07001522 }
1523
1524 public boolean isSimPinSecure() {
Jim Miller52a61332014-11-12 19:29:51 -08001525 // True if any SIM is pin secure
1526 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
1527 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
1528 }
1529 return false;
1530 }
1531
Jason Monk9ff69bd2014-12-02 16:43:17 -05001532 public State getSimState(int subId) {
Jim Miller52a61332014-11-12 19:29:51 -08001533 if (mSimDatas.containsKey(subId)) {
1534 return mSimDatas.get(subId).simState;
1535 } else {
1536 return State.UNKNOWN;
1537 }
1538 }
1539
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001540 /**
1541 * @return true if and only if the state has changed for the specified {@code slotId}
1542 */
1543 private boolean refreshSimState(int subId, int slotId) {
Jim Miller52a61332014-11-12 19:29:51 -08001544
1545 // This is awful. It exists because there are two APIs for getting the SIM status
1546 // that don't return the complete set of values and have different types. In Keyguard we
1547 // need IccCardConstants, but TelephonyManager would only give us
1548 // TelephonyManager.SIM_STATE*, so we retrieve it manually.
xinhe18b9c3c2014-12-02 15:03:20 -08001549 final TelephonyManager tele = TelephonyManager.from(mContext);
1550 int simState = tele.getSimState(slotId);
Jim Miller52a61332014-11-12 19:29:51 -08001551 State state;
1552 try {
xinhe18b9c3c2014-12-02 15:03:20 -08001553 state = State.intToState(simState);
Jim Miller52a61332014-11-12 19:29:51 -08001554 } catch(IllegalArgumentException ex) {
xinhe18b9c3c2014-12-02 15:03:20 -08001555 Log.w(TAG, "Unknown sim state: " + simState);
Jim Miller52a61332014-11-12 19:29:51 -08001556 state = State.UNKNOWN;
John Spurlock5b13e922015-01-07 11:04:58 -05001557 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001558 SimData data = mSimDatas.get(subId);
1559 final boolean changed;
1560 if (data == null) {
1561 data = new SimData(state, slotId, subId);
1562 mSimDatas.put(subId, data);
1563 changed = true; // no data yet; force update
1564 } else {
1565 changed = data.simState != state;
1566 data.simState = state;
1567 }
1568 return changed;
Jim Millerdcb3d842012-08-23 19:18:12 -07001569 }
1570
1571 public static boolean isSimPinSecure(IccCardConstants.State state) {
1572 final IccCardConstants.State simState = state;
1573 return (simState == IccCardConstants.State.PIN_REQUIRED
1574 || simState == IccCardConstants.State.PUK_REQUIRED
1575 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001576 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001577
1578 public DisplayClientState getCachedDisplayClientState() {
1579 return mDisplayClientState;
1580 }
Jim Miller20daffd2013-10-07 14:59:53 -07001581
1582 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1583 // (KeyguardViewMediator, KeyguardHostView)
Jorim Jaggi0d210f62015-07-10 14:24:44 -07001584 public void dispatchStartedWakingUp() {
1585 synchronized (this) {
1586 mDeviceInteractive = true;
1587 }
1588 mHandler.sendEmptyMessage(MSG_STARTED_WAKING_UP);
1589 }
1590
1591 public void dispatchFinishedGoingToSleep(int why) {
1592 synchronized(this) {
1593 mDeviceInteractive = false;
1594 }
1595 mHandler.sendMessage(mHandler.obtainMessage(MSG_FINISHED_GOING_TO_SLEEP, why, 0));
1596 }
1597
Jim Miller20daffd2013-10-07 14:59:53 -07001598 public void dispatchScreenTurnedOn() {
1599 synchronized (this) {
1600 mScreenOn = true;
1601 }
Jorim Jaggif1518da2015-07-30 11:56:36 -07001602 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
Jim Miller20daffd2013-10-07 14:59:53 -07001603 }
1604
Jorim Jaggi0d210f62015-07-10 14:24:44 -07001605 public void dispatchScreenTurnedOff() {
Jim Miller20daffd2013-10-07 14:59:53 -07001606 synchronized(this) {
1607 mScreenOn = false;
1608 }
Jorim Jaggif1518da2015-07-30 11:56:36 -07001609 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
Jim Miller20daffd2013-10-07 14:59:53 -07001610 }
1611
Jorim Jaggi0d210f62015-07-10 14:24:44 -07001612 public boolean isDeviceInteractive() {
1613 return mDeviceInteractive;
Jim Miller20daffd2013-10-07 14:59:53 -07001614 }
Jim Miller52a61332014-11-12 19:29:51 -08001615
1616 /**
1617 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
1618 * @param state
Wink Savilled09c4ca2014-11-22 10:08:16 -08001619 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
Jim Miller52a61332014-11-12 19:29:51 -08001620 */
1621 public int getNextSubIdForState(State state) {
1622 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
Wink Savilled09c4ca2014-11-22 10:08:16 -08001623 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Jim Miller52a61332014-11-12 19:29:51 -08001624 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
1625 for (int i = 0; i < list.size(); i++) {
1626 final SubscriptionInfo info = list.get(i);
1627 final int id = info.getSubscriptionId();
1628 int slotId = SubscriptionManager.getSlotId(id);
1629 if (state == getSimState(id) && bestSlotId > slotId ) {
1630 resultId = id;
1631 bestSlotId = slotId;
1632 }
1633 }
1634 return resultId;
1635 }
1636
1637 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) {
1638 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
1639 for (int i = 0; i < list.size(); i++) {
1640 SubscriptionInfo info = list.get(i);
1641 if (subId == info.getSubscriptionId()) return info;
1642 }
1643 return null; // not found
1644 }
Jason Monkab525272015-07-13 17:02:49 -04001645
1646 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1647 pw.println("KeyguardUpdateMonitor state:");
1648 pw.println(" SIM States:");
1649 for (SimData data : mSimDatas.values()) {
1650 pw.println(" " + data.toString());
1651 }
1652 pw.println(" Subs:");
1653 if (mSubscriptionInfo != null) {
1654 for (int i = 0; i < mSubscriptionInfo.size(); i++) {
1655 pw.println(" " + mSubscriptionInfo.get(i));
1656 }
1657 }
1658 pw.println(" Service states:");
1659 for (int subId : mServiceStates.keySet()) {
1660 pw.println(" " + subId + "=" + mServiceStates.get(subId));
1661 }
1662 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001663}