blob: 0795f650e24799b8f500afc0281d8b0325fd93fe [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;
Jim Millerf41fc962014-06-18 16:33:51 -070027import android.content.ContentResolver;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080028import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080031import android.database.ContentObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070032import android.graphics.Bitmap;
33
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080034import static android.os.BatteryManager.BATTERY_STATUS_FULL;
35import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
Jim Miller16464b82011-10-20 21:10:13 -070036import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
37import static android.os.BatteryManager.EXTRA_STATUS;
38import static android.os.BatteryManager.EXTRA_PLUGGED;
39import static android.os.BatteryManager.EXTRA_LEVEL;
40import static android.os.BatteryManager.EXTRA_HEALTH;
Jim Miller06e34502014-07-17 14:46:05 -070041
Jim Miller47088bb2009-11-24 00:40:16 -080042import android.media.AudioManager;
Jim Miller79a444a2011-02-15 15:02:11 -080043import android.os.BatteryManager;
Jim Miller9f0753f2015-03-23 23:59:22 -070044import android.os.CancellationSignal;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080045import android.os.Handler;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070046import android.os.IRemoteCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080047import android.os.Message;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070048import android.os.RemoteException;
Amith Yamasanie8e93a12013-05-09 18:12:30 -070049import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080050import android.provider.Settings;
Dianne Hackbornb7e787f2009-05-07 15:55:42 -070051
Wink Savillea639b312012-07-10 12:37:54 -070052import com.android.internal.telephony.IccCardConstants;
Jim Miller52a61332014-11-12 19:29:51 -080053import com.android.internal.telephony.IccCardConstants.State;
54import com.android.internal.telephony.PhoneConstants;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080055import com.android.internal.telephony.TelephonyIntents;
Jim Miller9f0753f2015-03-23 23:59:22 -070056
Jim Millerebbf2052015-03-31 17:24:34 -070057import android.hardware.fingerprint.FingerprintManager;
58import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
59import android.hardware.fingerprint.FingerprintUtils;
60import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
Jim Miller52a61332014-11-12 19:29:51 -080061import android.telephony.SubscriptionInfo;
Jim Miller52a61332014-11-12 19:29:51 -080062import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080063import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Jim Millerc23024d2010-02-24 15:37:00 -080064import android.telephony.TelephonyManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080065import android.util.Log;
Adrian Roos46842d92014-03-27 14:58:03 +010066import android.util.SparseBooleanArray;
Jorim Jaggi9f743032015-05-04 15:22:40 -070067import android.util.SparseIntArray;
Adrian Roos46842d92014-03-27 14:58:03 +010068
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080069import com.google.android.collect.Lists;
70
Jim Millerdcb3d842012-08-23 19:18:12 -070071import java.lang.ref.WeakReference;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080072import java.util.ArrayList;
Jim Miller52a61332014-11-12 19:29:51 -080073import java.util.HashMap;
74import java.util.List;
75import java.util.Map.Entry;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080076
77/**
78 * Watches for updates that may be interesting to the keyguard, and provides
79 * the up to date information as well as a registration for callbacks that care
80 * to be updated.
81 *
82 * Note: under time crunch, this has been extended to include some stuff that
83 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
Jim Miller258341c2012-08-30 16:50:10 -070084 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
85 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080086 */
Adrian Roos46842d92014-03-27 14:58:03 +010087public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080088
Jim Millerbbf1a742012-07-17 18:30:30 -070089 private static final String TAG = "KeyguardUpdateMonitor";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010090 private static final boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller52a61332014-11-12 19:29:51 -080091 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
Jim Millerbbf1a742012-07-17 18:30:30 -070092 private static final int LOW_BATTERY_THRESHOLD = 20;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080093
Jorim Jaggie7b12522014-08-06 16:41:21 +020094 private static final String ACTION_FACE_UNLOCK_STARTED
95 = "com.android.facelock.FACE_UNLOCK_STARTED";
96 private static final String ACTION_FACE_UNLOCK_STOPPED
97 = "com.android.facelock.FACE_UNLOCK_STOPPED";
98
Jim Millerbbf1a742012-07-17 18:30:30 -070099 // Callback messages
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800100 private static final int MSG_TIME_UPDATE = 301;
101 private static final int MSG_BATTERY_UPDATE = 302;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800102 private static final int MSG_SIM_STATE_CHANGE = 304;
Jim Miller47088bb2009-11-24 00:40:16 -0800103 private static final int MSG_RINGER_MODE_CHANGED = 305;
Jim Millerc23024d2010-02-24 15:37:00 -0800104 private static final int MSG_PHONE_STATE_CHANGED = 306;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700105 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -0700106 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500107 private static final int MSG_USER_SWITCHING = 310;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400108 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
Jim Millerf41fc962014-06-18 16:33:51 -0700109 private static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500110 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Millerf41fc962014-06-18 16:33:51 -0700111 private static final int MSG_USER_INFO_CHANGED = 317;
112 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jim Miller20daffd2013-10-07 14:59:53 -0700113 private static final int MSG_SCREEN_TURNED_ON = 319;
114 private static final int MSG_SCREEN_TURNED_OFF = 320;
Adrian Roosb6011622014-05-14 15:52:53 +0200115 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
Jim Miller9f0753f2015-03-23 23:59:22 -0700116 private static final int MSG_FINGERPRINT_AUTHENTICATED = 323;
117 private static final int MSG_FINGERPRINT_ERROR = 324;
118 private static final int MSG_FINGERPRINT_HELP = 325;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700119 private static final int MSG_FINGERPRINT_AUTH_FAILED = 326;
120 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327;
121 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800122
Jim Millerdcb3d842012-08-23 19:18:12 -0700123 private static KeyguardUpdateMonitor sInstance;
124
Jim Millerbbf1a742012-07-17 18:30:30 -0700125 private final Context mContext;
Jim Miller52a61332014-11-12 19:29:51 -0800126 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
Jim Millerbbf1a742012-07-17 18:30:30 -0700127
Jim Millerbbf1a742012-07-17 18:30:30 -0700128 private int mRingMode;
129 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400130 private boolean mKeyguardIsVisible;
Adrian Roosb6011622014-05-14 15:52:53 +0200131 private boolean mBouncer;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800132 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700133
Jim Millerdcb3d842012-08-23 19:18:12 -0700134 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700135 private boolean mDeviceProvisioned;
136
Jim Millerdcb3d842012-08-23 19:18:12 -0700137 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700138 private BatteryStatus mBatteryStatus;
139
Jim Millerdcb3d842012-08-23 19:18:12 -0700140 // Password attempts
Jorim Jaggi9f743032015-05-04 15:22:40 -0700141 private SparseIntArray mFailedAttempts = new SparseIntArray();
Brian Colonnacc4104f2012-10-09 17:50:46 -0400142
Jim Millerbbf1a742012-07-17 18:30:30 -0700143 private boolean mClockVisible;
144
Jim Miller6212cc02012-09-05 17:35:31 -0700145 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700146 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800147 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700148
Brian Colonnaa5239892013-04-15 11:45:40 -0400149 private boolean mSwitchingUser;
150
Jim Miller20daffd2013-10-07 14:59:53 -0700151 private boolean mScreenOn;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800152 private SubscriptionManager mSubscriptionManager;
153 private List<SubscriptionInfo> mSubscriptionInfo;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700154 private boolean mFingerprintDetectionRunning;
Jorim Jaggi237b0612015-05-01 14:28:49 -0700155 private TrustManager mTrustManager;
Jim Miller20daffd2013-10-07 14:59:53 -0700156
Jim Millerbbf1a742012-07-17 18:30:30 -0700157 private final Handler mHandler = new Handler() {
158 @Override
159 public void handleMessage(Message msg) {
160 switch (msg.what) {
161 case MSG_TIME_UPDATE:
162 handleTimeUpdate();
163 break;
164 case MSG_BATTERY_UPDATE:
165 handleBatteryUpdate((BatteryStatus) msg.obj);
166 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700167 case MSG_SIM_STATE_CHANGE:
Jim Miller52a61332014-11-12 19:29:51 -0800168 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700169 break;
170 case MSG_RINGER_MODE_CHANGED:
171 handleRingerModeChange(msg.arg1);
172 break;
173 case MSG_PHONE_STATE_CHANGED:
Adrian Roosb6011622014-05-14 15:52:53 +0200174 handlePhoneStateChanged((String) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700175 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700176 case MSG_DEVICE_PROVISIONED:
177 handleDeviceProvisioned();
178 break;
179 case MSG_DPM_STATE_CHANGED:
180 handleDevicePolicyManagerStateChanged();
181 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500182 case MSG_USER_SWITCHING:
Adrian Roosb6011622014-05-14 15:52:53 +0200183 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
Chris Wrenf41c61b2012-11-29 15:19:54 -0500184 break;
185 case MSG_USER_SWITCH_COMPLETE:
186 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700187 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400188 case MSG_KEYGUARD_VISIBILITY_CHANGED:
189 handleKeyguardVisibilityChanged(msg.arg1);
190 break;
Adrian Roosb6011622014-05-14 15:52:53 +0200191 case MSG_KEYGUARD_BOUNCER_CHANGED:
192 handleKeyguardBouncerChanged(msg.arg1);
193 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800194 case MSG_BOOT_COMPLETED:
195 handleBootCompleted();
196 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700197 case MSG_USER_INFO_CHANGED:
198 handleUserInfoChanged(msg.arg1);
199 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400200 case MSG_REPORT_EMERGENCY_CALL_ACTION:
201 handleReportEmergencyCallAction();
202 break;
Jim Miller20daffd2013-10-07 14:59:53 -0700203 case MSG_SCREEN_TURNED_OFF:
204 handleScreenTurnedOff(msg.arg1);
205 break;
206 case MSG_SCREEN_TURNED_ON:
207 handleScreenTurnedOn();
208 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700209 case MSG_FINGERPRINT_AUTHENTICATED:
210 handleFingerprintAuthenticated(msg.arg1, msg.arg2);
Jim Millerf41fc962014-06-18 16:33:51 -0700211 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700212 case MSG_FINGERPRINT_HELP:
213 handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
214 break;
215 case MSG_FINGERPRINT_ERROR:
216 handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
Jim Millerf41fc962014-06-18 16:33:51 -0700217 break;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700218 case MSG_FINGERPRINT_AUTH_FAILED:
219 handleFingerprintAuthFailed();
220 break;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200221 case MSG_FACE_UNLOCK_STATE_CHANGED:
Adrian Roos4a410172014-08-20 17:41:44 +0200222 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200223 break;
Jim Miller52a61332014-11-12 19:29:51 -0800224 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED:
225 handleSimSubscriptionInfoChanged();
226 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700227 }
228 }
229 };
230
Wink Savilled09c4ca2014-11-22 10:08:16 -0800231 private OnSubscriptionsChangedListener mSubscriptionListener =
232 new OnSubscriptionsChangedListener() {
Jim Miller52a61332014-11-12 19:29:51 -0800233 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800234 public void onSubscriptionsChanged() {
Jim Miller52a61332014-11-12 19:29:51 -0800235 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
236 }
237 };
238
Adrian Roos46842d92014-03-27 14:58:03 +0100239 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
Adrian Roos7861c662014-07-25 15:37:28 +0200240 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
Jim Miller9f0753f2015-03-23 23:59:22 -0700241 private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
Adrian Roos4a410172014-08-20 17:41:44 +0200242 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
Adrian Roos46842d92014-03-27 14:58:03 +0100243
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700244 private static int sCurrentUser;
245
246 public synchronized static void setCurrentUser(int currentUser) {
247 sCurrentUser = currentUser;
248 }
249
250 public synchronized static int getCurrentUser() {
251 return sCurrentUser;
252 }
253
Adrian Roos46842d92014-03-27 14:58:03 +0100254 @Override
Adrian Roos94e15a52015-04-16 12:23:18 -0700255 public void onTrustChanged(boolean enabled, int userId, int flags) {
Adrian Roos46842d92014-03-27 14:58:03 +0100256 mUserHasTrust.put(userId, enabled);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200257 for (int i = 0; i < mCallbacks.size(); i++) {
258 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
259 if (cb != null) {
260 cb.onTrustChanged(userId);
Adrian Roos94e15a52015-04-16 12:23:18 -0700261 if (enabled && flags != 0) {
262 cb.onTrustGrantedWithFlags(flags, userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200263 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200264 }
265 }
Adrian Roos46842d92014-03-27 14:58:03 +0100266 }
267
Jim Miller52a61332014-11-12 19:29:51 -0800268 protected void handleSimSubscriptionInfoChanged() {
269 if (DEBUG_SIM_STATES) {
270 Log.v(TAG, "onSubscriptionInfoChanged()");
Wink Savilled09c4ca2014-11-22 10:08:16 -0800271 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
272 if (sil != null) {
273 for (SubscriptionInfo subInfo : sil) {
274 Log.v(TAG, "SubInfo:" + subInfo);
275 }
276 } else {
277 Log.v(TAG, "onSubscriptionInfoChanged: list is null");
Jim Miller52a61332014-11-12 19:29:51 -0800278 }
279 }
280 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
281
282 // Hack level over 9000: Because the subscription id is not yet valid when we see the
283 // first update in handleSimStateChange, we need to force refresh all all SIM states
284 // so the subscription id for them is consistent.
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100285 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
Jim Miller52a61332014-11-12 19:29:51 -0800286 for (int i = 0; i < subscriptionInfos.size(); i++) {
287 SubscriptionInfo info = subscriptionInfos.get(i);
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100288 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
289 if (changed) {
290 changedSubscriptions.add(info);
291 }
Jim Miller52a61332014-11-12 19:29:51 -0800292 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100293 for (int i = 0; i < changedSubscriptions.size(); i++) {
294 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
Jim Miller52a61332014-11-12 19:29:51 -0800295 for (int j = 0; j < mCallbacks.size(); j++) {
296 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
297 if (cb != null) {
298 cb.onSimStateChanged(data.subId, data.slotId, data.simState);
299 }
300 }
301 }
Jason Monk6c985dc2015-01-09 16:07:14 -0500302 for (int j = 0; j < mCallbacks.size(); j++) {
303 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
304 if (cb != null) {
305 cb.onRefreshCarrierInfo();
306 }
307 }
Jim Miller52a61332014-11-12 19:29:51 -0800308 }
309
Wink Savilled09c4ca2014-11-22 10:08:16 -0800310 /** @return List of SubscriptionInfo records, maybe empty but never null */
Jim Miller52a61332014-11-12 19:29:51 -0800311 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
Wink Savilled09c4ca2014-11-22 10:08:16 -0800312 List<SubscriptionInfo> sil = mSubscriptionInfo;
313 if (sil == null || forceReload) {
314 sil = mSubscriptionManager.getActiveSubscriptionInfoList();
315 }
316 if (sil == null) {
317 // getActiveSubscriptionInfoList was null callers expect an empty list.
318 mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
319 } else {
320 mSubscriptionInfo = sil;
Jim Miller52a61332014-11-12 19:29:51 -0800321 }
322 return mSubscriptionInfo;
323 }
324
Adrian Roos7861c662014-07-25 15:37:28 +0200325 @Override
326 public void onTrustManagedChanged(boolean managed, int userId) {
327 mUserTrustIsManaged.put(userId, managed);
328
329 for (int i = 0; i < mCallbacks.size(); i++) {
330 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
331 if (cb != null) {
332 cb.onTrustManagedChanged(userId);
333 }
334 }
335 }
336
Jim Miller9f0753f2015-03-23 23:59:22 -0700337 private void onFingerprintAuthenticated(int userId) {
338 mUserFingerprintAuthenticated.put(userId, true);
Jim Millerf41fc962014-06-18 16:33:51 -0700339 for (int i = 0; i < mCallbacks.size(); i++) {
340 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
341 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700342 cb.onFingerprintAuthenticated(userId);
Jim Millerf41fc962014-06-18 16:33:51 -0700343 }
344 }
345 }
346
Jim Millerce7eb6d2015-04-03 19:29:13 -0700347 private void handleFingerprintAuthFailed() {
348 // FingerprintManager will allow us to retry a few times before finally giving up.
349 // TODO: Figure out the proper logic to stop this call when max tries is reached.
350 handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
351 }
Jim Millerf41fc962014-06-18 16:33:51 -0700352
Jim Millerce7eb6d2015-04-03 19:29:13 -0700353 private void handleFingerprintAuthenticated(int fingerId, int groupId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700354 try {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700355 final int userId;
356 try {
357 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
358 } catch (RemoteException e) {
359 Log.e(TAG, "Failed to get current user id: ", e);
360 return;
Jim Millerf41fc962014-06-18 16:33:51 -0700361 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700362 if (isFingerprintDisabled(userId)) {
363 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
364 return;
365 }
366 final ContentResolver res = mContext.getContentResolver();
367 final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
368 for (int i = 0; i < ids.length; i++) {
369 // TODO: fix once HAL supports storing group id
370 final boolean isCorrectUser = true || (groupId == userId);
371 if (ids[i] == fingerId && isCorrectUser) {
372 onFingerprintAuthenticated(userId);
373 }
374 }
375 } finally {
376 setFingerprintRunningDetectionRunning(false);
Jim Millerf41fc962014-06-18 16:33:51 -0700377 }
378 }
379
Jim Miller9f0753f2015-03-23 23:59:22 -0700380 private void handleFingerprintHelp(int msgId, String helpString) {
Jim Millerf41fc962014-06-18 16:33:51 -0700381 for (int i = 0; i < mCallbacks.size(); i++) {
382 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
383 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700384 cb.onFingerprintHelp(msgId, helpString);
385 }
386 }
387 }
388
389 private void handleFingerprintError(int msgId, String errString) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700390 setFingerprintRunningDetectionRunning(false);
Jim Miller9f0753f2015-03-23 23:59:22 -0700391 for (int i = 0; i < mCallbacks.size(); i++) {
392 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
393 if (cb != null) {
394 cb.onFingerprintError(msgId, errString);
Jim Millerf41fc962014-06-18 16:33:51 -0700395 }
396 }
397 }
398
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700399 private void setFingerprintRunningDetectionRunning(boolean running) {
400 if (running != mFingerprintDetectionRunning) {
401 mFingerprintDetectionRunning = running;
402 notifyFingerprintRunningStateChanged();
403 }
404 }
405
406 private void notifyFingerprintRunningStateChanged() {
407 for (int i = 0; i < mCallbacks.size(); i++) {
408 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
409 if (cb != null) {
410 cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
411 }
412 }
413 }
Adrian Roos4a410172014-08-20 17:41:44 +0200414 private void handleFaceUnlockStateChanged(boolean running, int userId) {
415 mUserFaceUnlockRunning.put(userId, running);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200416 for (int i = 0; i < mCallbacks.size(); i++) {
417 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
418 if (cb != null) {
Adrian Roos4a410172014-08-20 17:41:44 +0200419 cb.onFaceUnlockStateChanged(running, userId);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200420 }
421 }
422 }
423
Adrian Roos4a410172014-08-20 17:41:44 +0200424 public boolean isFaceUnlockRunning(int userId) {
425 return mUserFaceUnlockRunning.get(userId);
426 }
427
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700428 public boolean isFingerprintDetectionRunning() {
429 return mFingerprintDetectionRunning;
430 }
431
Jim Miller50e62182014-04-23 17:25:00 -0700432 private boolean isTrustDisabled(int userId) {
Adrian Roosa4da9f62015-02-21 01:15:21 +0100433 // Don't allow trust agent if device is secured with a SIM PIN. This is here
434 // mainly because there's no other way to prompt the user to enter their SIM PIN
435 // once they get past the keyguard screen.
436 final boolean disabledBySimPin = isSimPinSecure();
437 return disabledBySimPin;
Jim Miller50e62182014-04-23 17:25:00 -0700438 }
439
Jim Miller06e34502014-07-17 14:46:05 -0700440 private boolean isFingerprintDisabled(int userId) {
441 final DevicePolicyManager dpm =
442 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
443 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
444 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
445 }
446
Adrian Roos46842d92014-03-27 14:58:03 +0100447 public boolean getUserHasTrust(int userId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700448 return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
Jim Miller9f0753f2015-03-23 23:59:22 -0700449 || mUserFingerprintAuthenticated.get(userId);
Adrian Roos46842d92014-03-27 14:58:03 +0100450 }
451
Adrian Roos7861c662014-07-25 15:37:28 +0200452 public boolean getUserTrustIsManaged(int userId) {
453 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
454 }
455
Jim Miller8f09fd22013-03-14 19:04:28 -0700456 static class DisplayClientState {
457 public int clientGeneration;
458 public boolean clearing;
459 public PendingIntent intent;
460 public int playbackState;
461 public long playbackEventTime;
462 }
463
464 private DisplayClientState mDisplayClientState = new DisplayClientState();
465
Jim Millerbbf1a742012-07-17 18:30:30 -0700466 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
467
468 public void onReceive(Context context, Intent intent) {
469 final String action = intent.getAction();
470 if (DEBUG) Log.d(TAG, "received broadcast " + action);
471
472 if (Intent.ACTION_TIME_TICK.equals(action)
473 || Intent.ACTION_TIME_CHANGED.equals(action)
Adrian Roos48c796c2014-09-01 14:59:23 +0200474 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700475 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700476 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
477 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
478 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
479 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
480 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
481 final Message msg = mHandler.obtainMessage(
482 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
483 mHandler.sendMessage(msg);
484 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller52a61332014-11-12 19:29:51 -0800485 SimData args = SimData.fromIntent(intent);
Jim Millerbbf1a742012-07-17 18:30:30 -0700486 if (DEBUG_SIM_STATES) {
Jim Miller52a61332014-11-12 19:29:51 -0800487 Log.v(TAG, "action " + action
488 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
489 + " slotId: " + args.slotId + " subid: " + args.subId);
Jim Millerbbf1a742012-07-17 18:30:30 -0700490 }
Jim Miller52a61332014-11-12 19:29:51 -0800491 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
492 .sendToTarget();
Jim Millerbbf1a742012-07-17 18:30:30 -0700493 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
494 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
495 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
496 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
497 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
498 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800499 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700500 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700501 }
502 }
503 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700504
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700505 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
506
507 public void onReceive(Context context, Intent intent) {
508 final String action = intent.getAction();
Adrian Roos48c796c2014-09-01 14:59:23 +0200509 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
510 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
511 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700512 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
513 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
Adrian Roos48c796c2014-09-01 14:59:23 +0200514 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
515 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
516 getSendingUserId()));
517 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
518 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
519 getSendingUserId()));
520 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
521 .equals(action)) {
522 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700523 }
524 }
525 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700526
527 private FingerprintManager.AuthenticationCallback mAuthenticationCallback
528 = new AuthenticationCallback() {
Jim Millerf41fc962014-06-18 16:33:51 -0700529
530 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700531 public void onAuthenticationFailed() {
532 mHandler.obtainMessage(MSG_FINGERPRINT_AUTH_FAILED).sendToTarget();
533 };
534
535 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700536 public void onAuthenticationSucceeded(AuthenticationResult result) {
537 mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED,
538 result.getFingerprint().getFingerId(),
539 result.getFingerprint().getGroupId()).sendToTarget();
Jim Millerf41fc962014-06-18 16:33:51 -0700540 }
541
542 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700543 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
544 mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget();
545 }
546
547 @Override
548 public void onAuthenticationError(int errMsgId, CharSequence errString) {
Jorim Jaggi570de1e2015-05-01 15:08:34 -0700549 mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString).sendToTarget();
Jim Millerf41fc962014-06-18 16:33:51 -0700550 }
551 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700552 private CancellationSignal mFingerprintCancelSignal;
553 private FingerprintManager mFpm;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700554
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800555 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800556 * When we receive a
557 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700558 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800559 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800560 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800561 */
Jim Miller52a61332014-11-12 19:29:51 -0800562 private static class SimData {
563 public State simState;
564 public int slotId;
565 public int subId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800566
Jim Miller52a61332014-11-12 19:29:51 -0800567 SimData(State state, int slot, int id) {
Jim Miller90d5d462011-11-17 16:57:01 -0800568 simState = state;
Jim Miller52a61332014-11-12 19:29:51 -0800569 slotId = slot;
570 subId = id;
Jim Miller90d5d462011-11-17 16:57:01 -0800571 }
572
Jim Miller52a61332014-11-12 19:29:51 -0800573 static SimData fromIntent(Intent intent) {
574 State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800575 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
576 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
577 }
Wink Savillea639b312012-07-10 12:37:54 -0700578 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
Jim Miller52a61332014-11-12 19:29:51 -0800579 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
580 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
Wink Savilled09c4ca2014-11-22 10:08:16 -0800581 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea639b312012-07-10 12:37:54 -0700582 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700583 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700584 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700585
Wink Savillea639b312012-07-10 12:37:54 -0700586 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700587 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700588 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700589 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700590 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700591 }
Wink Savillea639b312012-07-10 12:37:54 -0700592 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
593 state = IccCardConstants.State.READY;
594 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800595 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700596 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
597 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
598 state = IccCardConstants.State.PIN_REQUIRED;
599 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
600 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800601 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700602 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800603 }
Wink Savillea639b312012-07-10 12:37:54 -0700604 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
605 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700606 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
607 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
608 // This is required because telephony doesn't return to "READY" after
609 // these state transitions. See bug 7197471.
610 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800611 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700612 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800613 }
Jim Miller52a61332014-11-12 19:29:51 -0800614 return new SimData(state, slotId, subId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800615 }
616
617 public String toString() {
Jim Miller52a61332014-11-12 19:29:51 -0800618 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800619 }
620 }
621
Adrian Roos12c1ef52014-06-04 13:54:08 +0200622 public static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700623 public final int status;
624 public final int level;
625 public final int plugged;
626 public final int health;
627 public BatteryStatus(int status, int level, int plugged, int health) {
628 this.status = status;
629 this.level = level;
630 this.plugged = plugged;
631 this.health = health;
632 }
633
Jim Millerbbf1a742012-07-17 18:30:30 -0700634 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700635 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700636 * @return true if the device is plugged in.
637 */
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100638 public boolean isPluggedIn() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700639 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700640 || plugged == BatteryManager.BATTERY_PLUGGED_USB
641 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700642 }
643
644 /**
645 * Whether or not the device is charged. Note that some devices never return 100% for
646 * battery level, so this allows either battery level or status to determine if the
647 * battery is charged.
648 * @return true if the device is charged
649 */
650 public boolean isCharged() {
651 return status == BATTERY_STATUS_FULL || level >= 100;
652 }
653
654 /**
655 * Whether battery is low and needs to be charged.
656 * @return true if battery is low
657 */
658 public boolean isBatteryLow() {
659 return level < LOW_BATTERY_THRESHOLD;
660 }
661
Jim Miller16464b82011-10-20 21:10:13 -0700662 }
663
Jim Millerdcb3d842012-08-23 19:18:12 -0700664 public static KeyguardUpdateMonitor getInstance(Context context) {
665 if (sInstance == null) {
666 sInstance = new KeyguardUpdateMonitor(context);
667 }
668 return sInstance;
669 }
670
Jim Miller20daffd2013-10-07 14:59:53 -0700671 protected void handleScreenTurnedOn() {
672 final int count = mCallbacks.size();
673 for (int i = 0; i < count; i++) {
674 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
675 if (cb != null) {
676 cb.onScreenTurnedOn();
677 }
678 }
Jorim Jaggiea657062015-04-28 13:45:11 -0700679 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700680 }
681
682 protected void handleScreenTurnedOff(int arg1) {
Jim Millerf41fc962014-06-18 16:33:51 -0700683 clearFingerprintRecognized();
Jim Miller20daffd2013-10-07 14:59:53 -0700684 final int count = mCallbacks.size();
685 for (int i = 0; i < count; i++) {
686 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
687 if (cb != null) {
688 cb.onScreenTurnedOff(arg1);
689 }
690 }
Jorim Jaggiea657062015-04-28 13:45:11 -0700691 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700692 }
693
Adam Powell43a372f2013-09-27 17:43:53 -0700694 /**
695 * IMPORTANT: Must be called from UI thread.
696 */
697 public void dispatchSetBackground(Bitmap bmp) {
698 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
699 final int count = mCallbacks.size();
700 for (int i = 0; i < count; i++) {
701 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
702 if (cb != null) {
703 cb.onSetBackground(bmp);
704 }
705 }
706 }
707
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700708 private void handleUserInfoChanged(int userId) {
709 for (int i = 0; i < mCallbacks.size(); i++) {
710 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
711 if (cb != null) {
712 cb.onUserInfoChanged(userId);
713 }
714 }
715 }
716
Jim Millerdcb3d842012-08-23 19:18:12 -0700717 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800718 mContext = context;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800719 mSubscriptionManager = SubscriptionManager.from(context);
Michael Jurkafff56142012-11-28 16:51:00 -0800720 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800721 // Since device can't be un-provisioned, we only need to register a content observer
722 // to update mDeviceProvisioned when we are...
723 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700724 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800725 }
Jim Miller47088bb2009-11-24 00:40:16 -0800726
Jim Millerbbf1a742012-07-17 18:30:30 -0700727 // Take a guess at initial SIM state, battery status and PLMN until we get an update
Jim Miller16464b82011-10-20 21:10:13 -0700728 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800729
Jim Millerbbf1a742012-07-17 18:30:30 -0700730 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800731 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800732 filter.addAction(Intent.ACTION_TIME_TICK);
733 filter.addAction(Intent.ACTION_TIME_CHANGED);
734 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
735 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
736 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800737 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Jim Miller47088bb2009-11-24 00:40:16 -0800738 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerbbf1a742012-07-17 18:30:30 -0700739 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700740
Adam Cohenc276e822012-11-08 13:01:08 -0800741 final IntentFilter bootCompleteFilter = new IntentFilter();
742 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
743 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
744 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
745
Adrian Roos48c796c2014-09-01 14:59:23 +0200746 final IntentFilter allUserFilter = new IntentFilter();
747 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
748 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
749 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
750 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
751 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
752 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700753 null, null);
754
Wink Saville071743f2015-01-12 17:11:04 -0800755 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700756 try {
757 ActivityManagerNative.getDefault().registerUserSwitchObserver(
758 new IUserSwitchObserver.Stub() {
759 @Override
760 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500761 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700762 newUserId, 0, reply));
763 }
764 @Override
765 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500766 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
Adrian Roosbe47b072014-09-03 00:08:56 +0200767 newUserId, 0));
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700768 }
Kenny Guy42979622015-04-13 18:03:05 +0000769 @Override
770 public void onForegroundProfileSwitch(int newProfileId) {
771 // Ignore.
772 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700773 });
774 } catch (RemoteException e) {
775 // TODO Auto-generated catch block
776 e.printStackTrace();
777 }
Adrian Roos46842d92014-03-27 14:58:03 +0100778
Jorim Jaggi237b0612015-05-01 14:28:49 -0700779 mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
780 mTrustManager.registerTrustListener(this);
Jim Millerf41fc962014-06-18 16:33:51 -0700781
Jim Miller9f0753f2015-03-23 23:59:22 -0700782 mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
Jorim Jaggiea657062015-04-28 13:45:11 -0700783 updateFingerprintListeningState();
784 }
785
786 private void updateFingerprintListeningState() {
787 boolean shouldListenForFingerprint = shouldListenForFingerprint();
788 if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
789 stopListeningForFingerprint();
790 } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
791 startListeningForFingerprint();
792 }
793 }
794
795 private boolean shouldListenForFingerprint() {
Jorim Jaggi237b0612015-05-01 14:28:49 -0700796 return mScreenOn && mKeyguardIsVisible && !mSwitchingUser
797 && mTrustManager.hasUserAuthenticatedSinceBoot(ActivityManager.getCurrentUser());
Jim Miller9f0753f2015-03-23 23:59:22 -0700798 }
799
Jim Millerce7eb6d2015-04-03 19:29:13 -0700800 private void startListeningForFingerprint() {
801 if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700802 int userId = ActivityManager.getCurrentUser();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700803 if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700804 && mFpm.getEnrolledFingerprints(userId).size() > 0) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700805 if (mFingerprintCancelSignal != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700806 mFingerprintCancelSignal.cancel();
807 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700808 mFingerprintCancelSignal = new CancellationSignal();
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700809 mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700810 setFingerprintRunningDetectionRunning(true);
Jim Miller9f0753f2015-03-23 23:59:22 -0700811 }
812 }
813
Jorim Jaggiea657062015-04-28 13:45:11 -0700814 private void stopListeningForFingerprint() {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700815 if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
816 if (isFingerprintDetectionRunning()) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700817 mFingerprintCancelSignal.cancel();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700818 mFingerprintCancelSignal = null;
Jim Miller9f0753f2015-03-23 23:59:22 -0700819 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700820 setFingerprintRunningDetectionRunning(false);
Jim Millerbbf1a742012-07-17 18:30:30 -0700821 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800822
Michael Jurkafff56142012-11-28 16:51:00 -0800823 private boolean isDeviceProvisionedInSettingsDb() {
824 return Settings.Global.getInt(mContext.getContentResolver(),
825 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
826 }
827
Jim Millerbbf1a742012-07-17 18:30:30 -0700828 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800829 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700830 @Override
831 public void onChange(boolean selfChange) {
832 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800833 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700834 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700835 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800836 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700837 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800838 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700839 };
840
841 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700842 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800843 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700844
845 // prevent a race condition between where we check the flag and where we register the
846 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800847 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700848 if (provisioned != mDeviceProvisioned) {
849 mDeviceProvisioned = provisioned;
850 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700851 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700852 }
853 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800854 }
855
Jim Millerbbf1a742012-07-17 18:30:30 -0700856 /**
857 * Handle {@link #MSG_DPM_STATE_CHANGED}
858 */
Jim Millerb0304762012-03-13 20:01:25 -0700859 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700860 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
861 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
862 if (cb != null) {
863 cb.onDevicePolicyManagerStateChanged();
864 }
Jim Millerb0304762012-03-13 20:01:25 -0700865 }
866 }
867
Jim Millerbbf1a742012-07-17 18:30:30 -0700868 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500869 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700870 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500871 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -0700872 mSwitchingUser = true;
873 updateFingerprintListeningState();
874
Jim Millerbbf1a742012-07-17 18:30:30 -0700875 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700876 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
877 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500878 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700879 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700880 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700881 try {
882 reply.sendResult(null);
883 } catch (RemoteException e) {
884 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700885 }
886
Jim Millerbbf1a742012-07-17 18:30:30 -0700887 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500888 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
889 */
890 protected void handleUserSwitchComplete(int userId) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -0700891 mSwitchingUser = false;
892 updateFingerprintListeningState();
893
Chris Wrenf41c61b2012-11-29 15:19:54 -0500894 for (int i = 0; i < mCallbacks.size(); i++) {
895 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
896 if (cb != null) {
897 cb.onUserSwitchComplete(userId);
898 }
899 }
900 }
901
902 /**
Jim Miller90873d52013-09-26 18:11:38 -0700903 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
904 * keyguard crashes sometime after boot, then it will never receive this
905 * broadcast and hence not handle the event. This method is ultimately called by
906 * PhoneWindowManager in this case.
907 */
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100908 public void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700909 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -0700910 }
911
912 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800913 * Handle {@link #MSG_BOOT_COMPLETED}
914 */
915 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700916 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800917 mBootCompleted = true;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800918 for (int i = 0; i < mCallbacks.size(); i++) {
919 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
920 if (cb != null) {
921 cb.onBootCompleted();
922 }
923 }
924 }
925
926 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800927 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800928 * destroyed.
929 */
930 public boolean hasBootCompleted() {
931 return mBootCompleted;
932 }
933
934 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700935 * Handle {@link #MSG_DEVICE_PROVISIONED}
936 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700937 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700938 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700939 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
940 if (cb != null) {
941 cb.onDeviceProvisioned();
942 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700943 }
Michael Jurkafff56142012-11-28 16:51:00 -0800944 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700945 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800946 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
947 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700948 }
949 }
950
Jim Millerbbf1a742012-07-17 18:30:30 -0700951 /**
952 * Handle {@link #MSG_PHONE_STATE_CHANGED}
953 */
Jim Millerc23024d2010-02-24 15:37:00 -0800954 protected void handlePhoneStateChanged(String newState) {
955 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700956 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
957 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
958 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
959 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
960 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
961 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
962 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700963 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700964 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
965 if (cb != null) {
966 cb.onPhoneStateChanged(mPhoneState);
967 }
Jim Millerc23024d2010-02-24 15:37:00 -0800968 }
969 }
970
Jim Millerbbf1a742012-07-17 18:30:30 -0700971 /**
972 * Handle {@link #MSG_RINGER_MODE_CHANGED}
973 */
Jim Miller47088bb2009-11-24 00:40:16 -0800974 protected void handleRingerModeChange(int mode) {
975 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700976 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700977 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700978 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
979 if (cb != null) {
980 cb.onRingerModeChanged(mode);
981 }
Jim Miller47088bb2009-11-24 00:40:16 -0800982 }
983 }
984
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800985 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800986 * Handle {@link #MSG_TIME_UPDATE}
987 */
988 private void handleTimeUpdate() {
989 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700990 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700991 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
992 if (cb != null) {
993 cb.onTimeChanged();
994 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800995 }
996 }
997
998 /**
999 * Handle {@link #MSG_BATTERY_UPDATE}
1000 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001001 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001002 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -07001003 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
1004 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -07001005 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001006 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001007 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1008 if (cb != null) {
1009 cb.onRefreshBatteryInfo(status);
1010 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001011 }
1012 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001013 }
1014
1015 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001016 * Handle {@link #MSG_SIM_STATE_CHANGE}
1017 */
Jim Miller52a61332014-11-12 19:29:51 -08001018 private void handleSimStateChange(int subId, int slotId, State state) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001019
Jim Miller52a61332014-11-12 19:29:51 -08001020 if (DEBUG_SIM_STATES) {
1021 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
1022 + slotId + ", state=" + state +")");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001023 }
1024
Wink Savillea54bf652014-12-11 13:37:50 -08001025 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Jim Miller52a61332014-11-12 19:29:51 -08001026 Log.w(TAG, "invalid subId in handleSimStateChange()");
1027 return;
1028 }
1029
1030 SimData data = mSimDatas.get(subId);
1031 final boolean changed;
1032 if (data == null) {
1033 data = new SimData(state, slotId, subId);
1034 mSimDatas.put(subId, data);
1035 changed = true; // no data yet; force update
1036 } else {
1037 changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
1038 data.simState = state;
1039 data.subId = subId;
1040 data.slotId = slotId;
1041 }
1042 if (changed && state != State.UNKNOWN) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001043 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001044 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1045 if (cb != null) {
Jim Miller52a61332014-11-12 19:29:51 -08001046 cb.onSimStateChanged(subId, slotId, state);
Jim Millerdcb3d842012-08-23 19:18:12 -07001047 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001048 }
1049 }
1050 }
1051
Jim Millerbbf1a742012-07-17 18:30:30 -07001052 /**
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001053 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
1054 */
1055 private void handleKeyguardVisibilityChanged(int showing) {
1056 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -04001057 boolean isShowing = (showing == 1);
1058 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001059 for (int i = 0; i < mCallbacks.size(); i++) {
1060 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1061 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -04001062 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001063 }
1064 }
Jorim Jaggiea657062015-04-28 13:45:11 -07001065 updateFingerprintListeningState();
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001066 }
1067
Brian Colonna7fce3802013-09-17 15:51:32 -04001068 /**
Adrian Roosb6011622014-05-14 15:52:53 +02001069 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
1070 * @see #sendKeyguardBouncerChanged(boolean)
1071 */
1072 private void handleKeyguardBouncerChanged(int bouncer) {
1073 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
1074 boolean isBouncer = (bouncer == 1);
1075 mBouncer = isBouncer;
1076 for (int i = 0; i < mCallbacks.size(); i++) {
1077 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1078 if (cb != null) {
1079 cb.onKeyguardBouncerChanged(isBouncer);
1080 }
1081 }
1082 }
1083
1084 /**
Brian Colonna7fce3802013-09-17 15:51:32 -04001085 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
1086 */
1087 private void handleReportEmergencyCallAction() {
1088 for (int i = 0; i < mCallbacks.size(); i++) {
1089 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1090 if (cb != null) {
1091 cb.onEmergencyCallAction();
1092 }
1093 }
1094 }
1095
Jim Miller16464b82011-10-20 21:10:13 -07001096 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001097 final boolean nowPluggedIn = current.isPluggedIn();
1098 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -08001099 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -07001100 wasPluggedIn == true && nowPluggedIn == true
1101 && (old.status != current.status);
1102
1103 // change in plug state is always interesting
1104 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001105 return true;
1106 }
1107
1108 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -07001109 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001110 return true;
1111 }
1112
Jim Miller16464b82011-10-20 21:10:13 -07001113 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -07001114 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -07001115 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001116 }
1117 return false;
1118 }
1119
1120 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001121 * Remove the given observer's callback.
1122 *
Jim Miller6212cc02012-09-05 17:35:31 -07001123 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001124 */
Jim Miller6212cc02012-09-05 17:35:31 -07001125 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1126 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1127 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1128 if (mCallbacks.get(i).get() == callback) {
1129 mCallbacks.remove(i);
1130 }
1131 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001132 }
1133
1134 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001135 * Register to receive notifications about general keyguard information
1136 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -07001137 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001138 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001139 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -07001140 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1141 // Prevent adding duplicate callbacks
1142 for (int i = 0; i < mCallbacks.size(); i++) {
1143 if (mCallbacks.get(i).get() == callback) {
1144 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1145 new Exception("Called by"));
1146 return;
Jim Millerdcb3d842012-08-23 19:18:12 -07001147 }
1148 }
Jim Miller6212cc02012-09-05 17:35:31 -07001149 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1150 removeCallback(null); // remove unused references
1151 sendUpdates(callback);
1152 }
1153
1154 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1155 // Notify listener of the current state
1156 callback.onRefreshBatteryInfo(mBatteryStatus);
1157 callback.onTimeChanged();
1158 callback.onRingerModeChanged(mRingMode);
1159 callback.onPhoneStateChanged(mPhoneState);
Jason Monk9ff69bd2014-12-02 16:43:17 -05001160 callback.onRefreshCarrierInfo();
Jim Miller6212cc02012-09-05 17:35:31 -07001161 callback.onClockVisibilityChanged();
Jim Miller52a61332014-11-12 19:29:51 -08001162 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
1163 final SimData state = data.getValue();
1164 callback.onSimStateChanged(state.subId, state.slotId, state.simState);
1165 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001166 }
1167
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001168 public void sendKeyguardVisibilityChanged(boolean showing) {
1169 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1170 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1171 message.arg1 = showing ? 1 : 0;
1172 message.sendToTarget();
1173 }
1174
Adrian Roosb6011622014-05-14 15:52:53 +02001175 /**
1176 * @see #handleKeyguardBouncerChanged(int)
1177 */
1178 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1179 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1180 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1181 message.arg1 = showingBouncer ? 1 : 0;
1182 message.sendToTarget();
1183 }
1184
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001185 /**
Jim Miller90d5d462011-11-17 16:57:01 -08001186 * 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 -08001187 * have the information earlier than waiting for the intent
1188 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -08001189 *
1190 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1191 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001192 */
Jim Miller52a61332014-11-12 19:29:51 -08001193 public void reportSimUnlocked(int subId) {
1194 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
1195 int slotId = SubscriptionManager.getSlotId(subId);
1196 handleSimStateChange(subId, slotId, State.READY);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001197 }
1198
Brian Colonna7fce3802013-09-17 15:51:32 -04001199 /**
1200 * Report that the emergency call button has been pressed and the emergency dialer is
1201 * about to be displayed.
1202 *
1203 * @param bypassHandler runs immediately.
1204 *
1205 * NOTE: Must be called from UI thread if bypassHandler == true.
1206 */
1207 public void reportEmergencyCallAction(boolean bypassHandler) {
1208 if (!bypassHandler) {
1209 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1210 } else {
1211 handleReportEmergencyCallAction();
1212 }
1213 }
1214
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001215 /**
1216 * @return Whether the device is provisioned (whether they have gone through
1217 * the setup wizard)
1218 */
1219 public boolean isDeviceProvisioned() {
1220 return mDeviceProvisioned;
1221 }
1222
Jorim Jaggi9f743032015-05-04 15:22:40 -07001223 public void clearFailedUnlockAttempts() {
1224 mFailedAttempts.delete(sCurrentUser);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001225 }
1226
Jorim Jaggi9f743032015-05-04 15:22:40 -07001227 public int getFailedUnlockAttempts() {
1228 return mFailedAttempts.get(sCurrentUser, 0);
1229 }
1230
1231 public void reportFailedUnlockAttempt() {
1232 mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001233 }
1234
Jim Millerf41fc962014-06-18 16:33:51 -07001235 public void clearFingerprintRecognized() {
Jim Miller9f0753f2015-03-23 23:59:22 -07001236 mUserFingerprintAuthenticated.clear();
Jim Millerf41fc962014-06-18 16:33:51 -07001237 }
1238
Jim Miller52a61332014-11-12 19:29:51 -08001239 public boolean isSimPinVoiceSecure() {
1240 // TODO: only count SIMs that handle voice
1241 return isSimPinSecure();
Jim Millerdcb3d842012-08-23 19:18:12 -07001242 }
1243
1244 public boolean isSimPinSecure() {
Jim Miller52a61332014-11-12 19:29:51 -08001245 // True if any SIM is pin secure
1246 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
1247 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
1248 }
1249 return false;
1250 }
1251
Jason Monk9ff69bd2014-12-02 16:43:17 -05001252 public State getSimState(int subId) {
Jim Miller52a61332014-11-12 19:29:51 -08001253 if (mSimDatas.containsKey(subId)) {
1254 return mSimDatas.get(subId).simState;
1255 } else {
1256 return State.UNKNOWN;
1257 }
1258 }
1259
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001260 /**
1261 * @return true if and only if the state has changed for the specified {@code slotId}
1262 */
1263 private boolean refreshSimState(int subId, int slotId) {
Jim Miller52a61332014-11-12 19:29:51 -08001264
1265 // This is awful. It exists because there are two APIs for getting the SIM status
1266 // that don't return the complete set of values and have different types. In Keyguard we
1267 // need IccCardConstants, but TelephonyManager would only give us
1268 // TelephonyManager.SIM_STATE*, so we retrieve it manually.
xinhe18b9c3c2014-12-02 15:03:20 -08001269 final TelephonyManager tele = TelephonyManager.from(mContext);
1270 int simState = tele.getSimState(slotId);
Jim Miller52a61332014-11-12 19:29:51 -08001271 State state;
1272 try {
xinhe18b9c3c2014-12-02 15:03:20 -08001273 state = State.intToState(simState);
Jim Miller52a61332014-11-12 19:29:51 -08001274 } catch(IllegalArgumentException ex) {
xinhe18b9c3c2014-12-02 15:03:20 -08001275 Log.w(TAG, "Unknown sim state: " + simState);
Jim Miller52a61332014-11-12 19:29:51 -08001276 state = State.UNKNOWN;
John Spurlock5b13e922015-01-07 11:04:58 -05001277 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001278 SimData data = mSimDatas.get(subId);
1279 final boolean changed;
1280 if (data == null) {
1281 data = new SimData(state, slotId, subId);
1282 mSimDatas.put(subId, data);
1283 changed = true; // no data yet; force update
1284 } else {
1285 changed = data.simState != state;
1286 data.simState = state;
1287 }
1288 return changed;
Jim Millerdcb3d842012-08-23 19:18:12 -07001289 }
1290
1291 public static boolean isSimPinSecure(IccCardConstants.State state) {
1292 final IccCardConstants.State simState = state;
1293 return (simState == IccCardConstants.State.PIN_REQUIRED
1294 || simState == IccCardConstants.State.PUK_REQUIRED
1295 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001296 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001297
1298 public DisplayClientState getCachedDisplayClientState() {
1299 return mDisplayClientState;
1300 }
Jim Miller20daffd2013-10-07 14:59:53 -07001301
1302 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1303 // (KeyguardViewMediator, KeyguardHostView)
1304 public void dispatchScreenTurnedOn() {
1305 synchronized (this) {
1306 mScreenOn = true;
1307 }
1308 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1309 }
1310
John Spurlock36a13422015-03-24 21:15:48 -04001311 public void dispatchScreenTurnedOff(int why) {
Jim Miller20daffd2013-10-07 14:59:53 -07001312 synchronized(this) {
1313 mScreenOn = false;
1314 }
1315 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1316 }
1317
1318 public boolean isScreenOn() {
1319 return mScreenOn;
1320 }
Jim Miller52a61332014-11-12 19:29:51 -08001321
1322 /**
1323 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
1324 * @param state
Wink Savilled09c4ca2014-11-22 10:08:16 -08001325 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
Jim Miller52a61332014-11-12 19:29:51 -08001326 */
1327 public int getNextSubIdForState(State state) {
1328 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
Wink Savilled09c4ca2014-11-22 10:08:16 -08001329 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Jim Miller52a61332014-11-12 19:29:51 -08001330 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
1331 for (int i = 0; i < list.size(); i++) {
1332 final SubscriptionInfo info = list.get(i);
1333 final int id = info.getSubscriptionId();
1334 int slotId = SubscriptionManager.getSlotId(id);
1335 if (state == getSimState(id) && bestSlotId > slotId ) {
1336 resultId = id;
1337 bestSlotId = slotId;
1338 }
1339 }
1340 return resultId;
1341 }
1342
1343 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) {
1344 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
1345 for (int i = 0; i < list.size(); i++) {
1346 SubscriptionInfo info = list.get(i);
1347 if (subId == info.getSubscriptionId()) return info;
1348 }
1349 return null; // not found
1350 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001351}