blob: 50c9f2d9aa38684f8a420a4a2e409d2586181bda [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;
Jim Millerce7eb6d2015-04-03 19:29:13 -070066import android.util.Slog;
Adrian Roos46842d92014-03-27 14:58:03 +010067import android.util.SparseBooleanArray;
68
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;
Jeff Sharkey054340d2011-09-01 22:28:03 -0700105 private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700106 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -0700107 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500108 private static final int MSG_USER_SWITCHING = 310;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400109 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
Jim Millerf41fc962014-06-18 16:33:51 -0700110 private static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500111 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Millerf41fc962014-06-18 16:33:51 -0700112 private static final int MSG_USER_INFO_CHANGED = 317;
113 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jim Miller20daffd2013-10-07 14:59:53 -0700114 private static final int MSG_SCREEN_TURNED_ON = 319;
115 private static final int MSG_SCREEN_TURNED_OFF = 320;
Adrian Roosb6011622014-05-14 15:52:53 +0200116 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
Jim Miller9f0753f2015-03-23 23:59:22 -0700117 private static final int MSG_FINGERPRINT_AUTHENTICATED = 323;
118 private static final int MSG_FINGERPRINT_ERROR = 324;
119 private static final int MSG_FINGERPRINT_HELP = 325;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700120 private static final int MSG_FINGERPRINT_AUTH_FAILED = 326;
121 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327;
122 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800123
Jim Millerdcb3d842012-08-23 19:18:12 -0700124 private static KeyguardUpdateMonitor sInstance;
125
Jim Millerbbf1a742012-07-17 18:30:30 -0700126 private final Context mContext;
Jim Miller52a61332014-11-12 19:29:51 -0800127 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
Jim Millerbbf1a742012-07-17 18:30:30 -0700128
Jim Millerbbf1a742012-07-17 18:30:30 -0700129 private int mRingMode;
130 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400131 private boolean mKeyguardIsVisible;
Adrian Roosb6011622014-05-14 15:52:53 +0200132 private boolean mBouncer;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800133 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700134
Jim Millerdcb3d842012-08-23 19:18:12 -0700135 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700136 private boolean mDeviceProvisioned;
137
Jim Millerdcb3d842012-08-23 19:18:12 -0700138 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700139 private BatteryStatus mBatteryStatus;
140
Jim Millerdcb3d842012-08-23 19:18:12 -0700141 // Password attempts
Jim Millerbbf1a742012-07-17 18:30:30 -0700142 private int mFailedAttempts = 0;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400143
Jim Millerbbf1a742012-07-17 18:30:30 -0700144 private boolean mClockVisible;
145
Jim Miller6212cc02012-09-05 17:35:31 -0700146 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700147 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800148 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700149
Brian Colonnaa5239892013-04-15 11:45:40 -0400150 private boolean mSwitchingUser;
151
Jim Miller20daffd2013-10-07 14:59:53 -0700152 private boolean mScreenOn;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800153 private SubscriptionManager mSubscriptionManager;
154 private List<SubscriptionInfo> mSubscriptionInfo;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700155 private boolean mFingerprintDetectionRunning;
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;
176 case MSG_CLOCK_VISIBILITY_CHANGED:
177 handleClockVisibilityChanged();
178 break;
179 case MSG_DEVICE_PROVISIONED:
180 handleDeviceProvisioned();
181 break;
182 case MSG_DPM_STATE_CHANGED:
183 handleDevicePolicyManagerStateChanged();
184 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500185 case MSG_USER_SWITCHING:
Adrian Roosb6011622014-05-14 15:52:53 +0200186 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
Chris Wrenf41c61b2012-11-29 15:19:54 -0500187 break;
188 case MSG_USER_SWITCH_COMPLETE:
189 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700190 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400191 case MSG_KEYGUARD_VISIBILITY_CHANGED:
192 handleKeyguardVisibilityChanged(msg.arg1);
193 break;
Adrian Roosb6011622014-05-14 15:52:53 +0200194 case MSG_KEYGUARD_BOUNCER_CHANGED:
195 handleKeyguardBouncerChanged(msg.arg1);
196 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800197 case MSG_BOOT_COMPLETED:
198 handleBootCompleted();
199 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700200 case MSG_USER_INFO_CHANGED:
201 handleUserInfoChanged(msg.arg1);
202 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400203 case MSG_REPORT_EMERGENCY_CALL_ACTION:
204 handleReportEmergencyCallAction();
205 break;
Jim Miller20daffd2013-10-07 14:59:53 -0700206 case MSG_SCREEN_TURNED_OFF:
207 handleScreenTurnedOff(msg.arg1);
208 break;
209 case MSG_SCREEN_TURNED_ON:
210 handleScreenTurnedOn();
211 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700212 case MSG_FINGERPRINT_AUTHENTICATED:
213 handleFingerprintAuthenticated(msg.arg1, msg.arg2);
Jim Millerf41fc962014-06-18 16:33:51 -0700214 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700215 case MSG_FINGERPRINT_HELP:
216 handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
217 break;
218 case MSG_FINGERPRINT_ERROR:
219 handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
Jim Millerf41fc962014-06-18 16:33:51 -0700220 break;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700221 case MSG_FINGERPRINT_AUTH_FAILED:
222 handleFingerprintAuthFailed();
223 break;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200224 case MSG_FACE_UNLOCK_STATE_CHANGED:
Adrian Roos4a410172014-08-20 17:41:44 +0200225 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200226 break;
Jim Miller52a61332014-11-12 19:29:51 -0800227 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED:
228 handleSimSubscriptionInfoChanged();
229 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700230 }
231 }
232 };
233
Wink Savilled09c4ca2014-11-22 10:08:16 -0800234 private OnSubscriptionsChangedListener mSubscriptionListener =
235 new OnSubscriptionsChangedListener() {
Jim Miller52a61332014-11-12 19:29:51 -0800236 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800237 public void onSubscriptionsChanged() {
Jim Miller52a61332014-11-12 19:29:51 -0800238 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
239 }
240 };
241
Adrian Roos46842d92014-03-27 14:58:03 +0100242 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
Adrian Roos7861c662014-07-25 15:37:28 +0200243 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
Jim Miller9f0753f2015-03-23 23:59:22 -0700244 private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
Adrian Roos4a410172014-08-20 17:41:44 +0200245 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
Adrian Roos46842d92014-03-27 14:58:03 +0100246
247 @Override
Adrian Roos3c9a3502014-08-06 19:09:45 +0200248 public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
Adrian Roos46842d92014-03-27 14:58:03 +0100249 mUserHasTrust.put(userId, enabled);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200250
251 for (int i = 0; i < mCallbacks.size(); i++) {
252 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
253 if (cb != null) {
254 cb.onTrustChanged(userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200255 if (enabled && initiatedByUser) {
256 cb.onTrustInitiatedByUser(userId);
257 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200258 }
259 }
Adrian Roos46842d92014-03-27 14:58:03 +0100260 }
261
Jim Miller52a61332014-11-12 19:29:51 -0800262 protected void handleSimSubscriptionInfoChanged() {
263 if (DEBUG_SIM_STATES) {
264 Log.v(TAG, "onSubscriptionInfoChanged()");
Wink Savilled09c4ca2014-11-22 10:08:16 -0800265 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
266 if (sil != null) {
267 for (SubscriptionInfo subInfo : sil) {
268 Log.v(TAG, "SubInfo:" + subInfo);
269 }
270 } else {
271 Log.v(TAG, "onSubscriptionInfoChanged: list is null");
Jim Miller52a61332014-11-12 19:29:51 -0800272 }
273 }
274 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
275
276 // Hack level over 9000: Because the subscription id is not yet valid when we see the
277 // first update in handleSimStateChange, we need to force refresh all all SIM states
278 // so the subscription id for them is consistent.
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100279 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
Jim Miller52a61332014-11-12 19:29:51 -0800280 for (int i = 0; i < subscriptionInfos.size(); i++) {
281 SubscriptionInfo info = subscriptionInfos.get(i);
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100282 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
283 if (changed) {
284 changedSubscriptions.add(info);
285 }
Jim Miller52a61332014-11-12 19:29:51 -0800286 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100287 for (int i = 0; i < changedSubscriptions.size(); i++) {
288 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
Jim Miller52a61332014-11-12 19:29:51 -0800289 for (int j = 0; j < mCallbacks.size(); j++) {
290 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
291 if (cb != null) {
292 cb.onSimStateChanged(data.subId, data.slotId, data.simState);
293 }
294 }
295 }
Jason Monk6c985dc2015-01-09 16:07:14 -0500296 for (int j = 0; j < mCallbacks.size(); j++) {
297 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
298 if (cb != null) {
299 cb.onRefreshCarrierInfo();
300 }
301 }
Jim Miller52a61332014-11-12 19:29:51 -0800302 }
303
Wink Savilled09c4ca2014-11-22 10:08:16 -0800304 /** @return List of SubscriptionInfo records, maybe empty but never null */
Jim Miller52a61332014-11-12 19:29:51 -0800305 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
Wink Savilled09c4ca2014-11-22 10:08:16 -0800306 List<SubscriptionInfo> sil = mSubscriptionInfo;
307 if (sil == null || forceReload) {
308 sil = mSubscriptionManager.getActiveSubscriptionInfoList();
309 }
310 if (sil == null) {
311 // getActiveSubscriptionInfoList was null callers expect an empty list.
312 mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
313 } else {
314 mSubscriptionInfo = sil;
Jim Miller52a61332014-11-12 19:29:51 -0800315 }
316 return mSubscriptionInfo;
317 }
318
Adrian Roos7861c662014-07-25 15:37:28 +0200319 @Override
320 public void onTrustManagedChanged(boolean managed, int userId) {
321 mUserTrustIsManaged.put(userId, managed);
322
323 for (int i = 0; i < mCallbacks.size(); i++) {
324 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
325 if (cb != null) {
326 cb.onTrustManagedChanged(userId);
327 }
328 }
329 }
330
Jim Miller9f0753f2015-03-23 23:59:22 -0700331 private void onFingerprintAuthenticated(int userId) {
332 mUserFingerprintAuthenticated.put(userId, true);
Jim Millerf41fc962014-06-18 16:33:51 -0700333 for (int i = 0; i < mCallbacks.size(); i++) {
334 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
335 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700336 cb.onFingerprintAuthenticated(userId);
Jim Millerf41fc962014-06-18 16:33:51 -0700337 }
338 }
339 }
340
Jim Millerce7eb6d2015-04-03 19:29:13 -0700341 private void handleFingerprintAuthFailed() {
342 // FingerprintManager will allow us to retry a few times before finally giving up.
343 // TODO: Figure out the proper logic to stop this call when max tries is reached.
344 handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
345 }
Jim Millerf41fc962014-06-18 16:33:51 -0700346
Jim Millerce7eb6d2015-04-03 19:29:13 -0700347 private void handleFingerprintAuthenticated(int fingerId, int groupId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700348 try {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700349 final int userId;
350 try {
351 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
352 } catch (RemoteException e) {
353 Log.e(TAG, "Failed to get current user id: ", e);
354 return;
Jim Millerf41fc962014-06-18 16:33:51 -0700355 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700356 if (isFingerprintDisabled(userId)) {
357 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
358 return;
359 }
360 final ContentResolver res = mContext.getContentResolver();
361 final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
362 for (int i = 0; i < ids.length; i++) {
363 // TODO: fix once HAL supports storing group id
364 final boolean isCorrectUser = true || (groupId == userId);
365 if (ids[i] == fingerId && isCorrectUser) {
366 onFingerprintAuthenticated(userId);
367 }
368 }
369 } finally {
370 setFingerprintRunningDetectionRunning(false);
Jim Millerf41fc962014-06-18 16:33:51 -0700371 }
372 }
373
Jim Miller9f0753f2015-03-23 23:59:22 -0700374 private void handleFingerprintHelp(int msgId, String helpString) {
Jim Millerf41fc962014-06-18 16:33:51 -0700375 for (int i = 0; i < mCallbacks.size(); i++) {
376 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
377 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700378 cb.onFingerprintHelp(msgId, helpString);
379 }
380 }
381 }
382
383 private void handleFingerprintError(int msgId, String errString) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700384 setFingerprintRunningDetectionRunning(false);
Jim Miller9f0753f2015-03-23 23:59:22 -0700385 for (int i = 0; i < mCallbacks.size(); i++) {
386 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
387 if (cb != null) {
388 cb.onFingerprintError(msgId, errString);
Jim Millerf41fc962014-06-18 16:33:51 -0700389 }
390 }
391 }
392
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700393 private void setFingerprintRunningDetectionRunning(boolean running) {
394 if (running != mFingerprintDetectionRunning) {
395 mFingerprintDetectionRunning = running;
396 notifyFingerprintRunningStateChanged();
397 }
398 }
399
400 private void notifyFingerprintRunningStateChanged() {
401 for (int i = 0; i < mCallbacks.size(); i++) {
402 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
403 if (cb != null) {
404 cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
405 }
406 }
407 }
Adrian Roos4a410172014-08-20 17:41:44 +0200408 private void handleFaceUnlockStateChanged(boolean running, int userId) {
409 mUserFaceUnlockRunning.put(userId, running);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200410 for (int i = 0; i < mCallbacks.size(); i++) {
411 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
412 if (cb != null) {
Adrian Roos4a410172014-08-20 17:41:44 +0200413 cb.onFaceUnlockStateChanged(running, userId);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200414 }
415 }
416 }
417
Adrian Roos4a410172014-08-20 17:41:44 +0200418 public boolean isFaceUnlockRunning(int userId) {
419 return mUserFaceUnlockRunning.get(userId);
420 }
421
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700422 public boolean isFingerprintDetectionRunning() {
423 return mFingerprintDetectionRunning;
424 }
425
Jim Miller50e62182014-04-23 17:25:00 -0700426 private boolean isTrustDisabled(int userId) {
Adrian Roosa4da9f62015-02-21 01:15:21 +0100427 // Don't allow trust agent if device is secured with a SIM PIN. This is here
428 // mainly because there's no other way to prompt the user to enter their SIM PIN
429 // once they get past the keyguard screen.
430 final boolean disabledBySimPin = isSimPinSecure();
431 return disabledBySimPin;
Jim Miller50e62182014-04-23 17:25:00 -0700432 }
433
Jim Miller06e34502014-07-17 14:46:05 -0700434 private boolean isFingerprintDisabled(int userId) {
435 final DevicePolicyManager dpm =
436 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
437 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
438 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
439 }
440
Adrian Roos46842d92014-03-27 14:58:03 +0100441 public boolean getUserHasTrust(int userId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700442 return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
Jim Miller9f0753f2015-03-23 23:59:22 -0700443 || mUserFingerprintAuthenticated.get(userId);
Adrian Roos46842d92014-03-27 14:58:03 +0100444 }
445
Adrian Roos7861c662014-07-25 15:37:28 +0200446 public boolean getUserTrustIsManaged(int userId) {
447 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
448 }
449
Jim Miller8f09fd22013-03-14 19:04:28 -0700450 static class DisplayClientState {
451 public int clientGeneration;
452 public boolean clearing;
453 public PendingIntent intent;
454 public int playbackState;
455 public long playbackEventTime;
456 }
457
458 private DisplayClientState mDisplayClientState = new DisplayClientState();
459
Jim Millerbbf1a742012-07-17 18:30:30 -0700460 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
461
462 public void onReceive(Context context, Intent intent) {
463 final String action = intent.getAction();
464 if (DEBUG) Log.d(TAG, "received broadcast " + action);
465
466 if (Intent.ACTION_TIME_TICK.equals(action)
467 || Intent.ACTION_TIME_CHANGED.equals(action)
Adrian Roos48c796c2014-09-01 14:59:23 +0200468 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700469 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700470 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
471 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
472 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
473 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
474 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
475 final Message msg = mHandler.obtainMessage(
476 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
477 mHandler.sendMessage(msg);
478 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller52a61332014-11-12 19:29:51 -0800479 SimData args = SimData.fromIntent(intent);
Jim Millerbbf1a742012-07-17 18:30:30 -0700480 if (DEBUG_SIM_STATES) {
Jim Miller52a61332014-11-12 19:29:51 -0800481 Log.v(TAG, "action " + action
482 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
483 + " slotId: " + args.slotId + " subid: " + args.subId);
Jim Millerbbf1a742012-07-17 18:30:30 -0700484 }
Jim Miller52a61332014-11-12 19:29:51 -0800485 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
486 .sendToTarget();
Jim Millerbbf1a742012-07-17 18:30:30 -0700487 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
488 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
489 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
490 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
491 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
492 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800493 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700494 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700495 }
496 }
497 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700498
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700499 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
500
501 public void onReceive(Context context, Intent intent) {
502 final String action = intent.getAction();
Adrian Roos48c796c2014-09-01 14:59:23 +0200503 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
504 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
505 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700506 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
507 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
Adrian Roos48c796c2014-09-01 14:59:23 +0200508 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
509 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
510 getSendingUserId()));
511 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
512 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
513 getSendingUserId()));
514 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
515 .equals(action)) {
516 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700517 }
518 }
519 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700520
521 private FingerprintManager.AuthenticationCallback mAuthenticationCallback
522 = new AuthenticationCallback() {
Jim Millerf41fc962014-06-18 16:33:51 -0700523
524 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700525 public void onAuthenticationFailed() {
526 mHandler.obtainMessage(MSG_FINGERPRINT_AUTH_FAILED).sendToTarget();
527 };
528
529 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700530 public void onAuthenticationSucceeded(AuthenticationResult result) {
531 mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED,
532 result.getFingerprint().getFingerId(),
533 result.getFingerprint().getGroupId()).sendToTarget();
Jim Millerf41fc962014-06-18 16:33:51 -0700534 }
535
536 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700537 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
538 mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget();
539 }
540
541 @Override
542 public void onAuthenticationError(int errMsgId, CharSequence errString) {
543 mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString);
Jim Millerf41fc962014-06-18 16:33:51 -0700544 }
545 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700546 private CancellationSignal mFingerprintCancelSignal;
547 private FingerprintManager mFpm;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700548
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800549 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800550 * When we receive a
551 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700552 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800553 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800554 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800555 */
Jim Miller52a61332014-11-12 19:29:51 -0800556 private static class SimData {
557 public State simState;
558 public int slotId;
559 public int subId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800560
Jim Miller52a61332014-11-12 19:29:51 -0800561 SimData(State state, int slot, int id) {
Jim Miller90d5d462011-11-17 16:57:01 -0800562 simState = state;
Jim Miller52a61332014-11-12 19:29:51 -0800563 slotId = slot;
564 subId = id;
Jim Miller90d5d462011-11-17 16:57:01 -0800565 }
566
Jim Miller52a61332014-11-12 19:29:51 -0800567 static SimData fromIntent(Intent intent) {
568 State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800569 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
570 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
571 }
Wink Savillea639b312012-07-10 12:37:54 -0700572 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
Jim Miller52a61332014-11-12 19:29:51 -0800573 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
574 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
Wink Savilled09c4ca2014-11-22 10:08:16 -0800575 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea639b312012-07-10 12:37:54 -0700576 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700577 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700578 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700579
Wink Savillea639b312012-07-10 12:37:54 -0700580 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700581 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700582 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700583 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700584 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700585 }
Wink Savillea639b312012-07-10 12:37:54 -0700586 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
587 state = IccCardConstants.State.READY;
588 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800589 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700590 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
591 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
592 state = IccCardConstants.State.PIN_REQUIRED;
593 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
594 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800595 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700596 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800597 }
Wink Savillea639b312012-07-10 12:37:54 -0700598 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
599 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700600 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
601 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
602 // This is required because telephony doesn't return to "READY" after
603 // these state transitions. See bug 7197471.
604 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800605 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700606 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800607 }
Jim Miller52a61332014-11-12 19:29:51 -0800608 return new SimData(state, slotId, subId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800609 }
610
611 public String toString() {
Jim Miller52a61332014-11-12 19:29:51 -0800612 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800613 }
614 }
615
Adrian Roos12c1ef52014-06-04 13:54:08 +0200616 public static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700617 public final int status;
618 public final int level;
619 public final int plugged;
620 public final int health;
621 public BatteryStatus(int status, int level, int plugged, int health) {
622 this.status = status;
623 this.level = level;
624 this.plugged = plugged;
625 this.health = health;
626 }
627
Jim Millerbbf1a742012-07-17 18:30:30 -0700628 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700629 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700630 * @return true if the device is plugged in.
631 */
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100632 public boolean isPluggedIn() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700633 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700634 || plugged == BatteryManager.BATTERY_PLUGGED_USB
635 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700636 }
637
638 /**
639 * Whether or not the device is charged. Note that some devices never return 100% for
640 * battery level, so this allows either battery level or status to determine if the
641 * battery is charged.
642 * @return true if the device is charged
643 */
644 public boolean isCharged() {
645 return status == BATTERY_STATUS_FULL || level >= 100;
646 }
647
648 /**
649 * Whether battery is low and needs to be charged.
650 * @return true if battery is low
651 */
652 public boolean isBatteryLow() {
653 return level < LOW_BATTERY_THRESHOLD;
654 }
655
Jim Miller16464b82011-10-20 21:10:13 -0700656 }
657
Jim Millerdcb3d842012-08-23 19:18:12 -0700658 public static KeyguardUpdateMonitor getInstance(Context context) {
659 if (sInstance == null) {
660 sInstance = new KeyguardUpdateMonitor(context);
661 }
662 return sInstance;
663 }
664
Jim Miller20daffd2013-10-07 14:59:53 -0700665 protected void handleScreenTurnedOn() {
666 final int count = mCallbacks.size();
667 for (int i = 0; i < count; i++) {
668 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
669 if (cb != null) {
670 cb.onScreenTurnedOn();
671 }
672 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700673 startListeningForFingerprint();
Jim Miller20daffd2013-10-07 14:59:53 -0700674 }
675
676 protected void handleScreenTurnedOff(int arg1) {
Jim Millerf41fc962014-06-18 16:33:51 -0700677 clearFingerprintRecognized();
Jim Miller20daffd2013-10-07 14:59:53 -0700678 final int count = mCallbacks.size();
679 for (int i = 0; i < count; i++) {
680 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
681 if (cb != null) {
682 cb.onScreenTurnedOff(arg1);
683 }
684 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700685 stopListeningForFingerprint();
Jim Miller20daffd2013-10-07 14:59:53 -0700686 }
687
Adam Powell43a372f2013-09-27 17:43:53 -0700688 /**
689 * IMPORTANT: Must be called from UI thread.
690 */
691 public void dispatchSetBackground(Bitmap bmp) {
692 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
693 final int count = mCallbacks.size();
694 for (int i = 0; i < count; i++) {
695 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
696 if (cb != null) {
697 cb.onSetBackground(bmp);
698 }
699 }
700 }
701
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700702 private void handleUserInfoChanged(int userId) {
703 for (int i = 0; i < mCallbacks.size(); i++) {
704 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
705 if (cb != null) {
706 cb.onUserInfoChanged(userId);
707 }
708 }
709 }
710
Jim Millerdcb3d842012-08-23 19:18:12 -0700711 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800712 mContext = context;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800713 mSubscriptionManager = SubscriptionManager.from(context);
Michael Jurkafff56142012-11-28 16:51:00 -0800714 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800715 // Since device can't be un-provisioned, we only need to register a content observer
716 // to update mDeviceProvisioned when we are...
717 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700718 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800719 }
Jim Miller47088bb2009-11-24 00:40:16 -0800720
Jim Millerbbf1a742012-07-17 18:30:30 -0700721 // Take a guess at initial SIM state, battery status and PLMN until we get an update
Jim Miller16464b82011-10-20 21:10:13 -0700722 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800723
Jim Millerbbf1a742012-07-17 18:30:30 -0700724 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800725 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800726 filter.addAction(Intent.ACTION_TIME_TICK);
727 filter.addAction(Intent.ACTION_TIME_CHANGED);
728 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
729 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
730 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800731 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Jim Miller47088bb2009-11-24 00:40:16 -0800732 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerbbf1a742012-07-17 18:30:30 -0700733 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700734
Adam Cohenc276e822012-11-08 13:01:08 -0800735 final IntentFilter bootCompleteFilter = new IntentFilter();
736 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
737 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
738 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
739
Adrian Roos48c796c2014-09-01 14:59:23 +0200740 final IntentFilter allUserFilter = new IntentFilter();
741 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
742 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
743 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
744 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
745 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
746 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700747 null, null);
748
Wink Saville071743f2015-01-12 17:11:04 -0800749 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700750 try {
751 ActivityManagerNative.getDefault().registerUserSwitchObserver(
752 new IUserSwitchObserver.Stub() {
753 @Override
754 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500755 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700756 newUserId, 0, reply));
Brian Colonnaa5239892013-04-15 11:45:40 -0400757 mSwitchingUser = true;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700758 stopListeningForFingerprint();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700759 }
760 @Override
761 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500762 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
Adrian Roosbe47b072014-09-03 00:08:56 +0200763 newUserId, 0));
Brian Colonnaa5239892013-04-15 11:45:40 -0400764 mSwitchingUser = false;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700765 startListeningForFingerprint();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700766 }
Kenny Guy42979622015-04-13 18:03:05 +0000767 @Override
768 public void onForegroundProfileSwitch(int newProfileId) {
769 // Ignore.
770 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700771 });
772 } catch (RemoteException e) {
773 // TODO Auto-generated catch block
774 e.printStackTrace();
775 }
Adrian Roos46842d92014-03-27 14:58:03 +0100776
777 TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
778 trustManager.registerTrustListener(this);
Jim Millerf41fc962014-06-18 16:33:51 -0700779
Jim Miller9f0753f2015-03-23 23:59:22 -0700780 mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700781 startListeningForFingerprint();
Jim Miller9f0753f2015-03-23 23:59:22 -0700782 }
783
Jim Millerce7eb6d2015-04-03 19:29:13 -0700784 private void startListeningForFingerprint() {
785 if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700786 int userId = ActivityManager.getCurrentUser();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700787 if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700788 && mFpm.getEnrolledFingerprints(userId).size() > 0) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700789 if (mFingerprintCancelSignal != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700790 mFingerprintCancelSignal.cancel();
791 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700792 mFingerprintCancelSignal = new CancellationSignal();
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700793 mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700794 setFingerprintRunningDetectionRunning(true);
Jim Miller9f0753f2015-03-23 23:59:22 -0700795 }
796 }
797
Jim Millerce7eb6d2015-04-03 19:29:13 -0700798 public void stopListeningForFingerprint() {
799 if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
800 if (isFingerprintDetectionRunning()) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700801 mFingerprintCancelSignal.cancel();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700802 mFingerprintCancelSignal = null;
Jim Miller9f0753f2015-03-23 23:59:22 -0700803 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700804 setFingerprintRunningDetectionRunning(false);
Jim Millerbbf1a742012-07-17 18:30:30 -0700805 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800806
Michael Jurkafff56142012-11-28 16:51:00 -0800807 private boolean isDeviceProvisionedInSettingsDb() {
808 return Settings.Global.getInt(mContext.getContentResolver(),
809 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
810 }
811
Jim Millerbbf1a742012-07-17 18:30:30 -0700812 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800813 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700814 @Override
815 public void onChange(boolean selfChange) {
816 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800817 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700818 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700819 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800820 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700821 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800822 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700823 };
824
825 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700826 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800827 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700828
829 // prevent a race condition between where we check the flag and where we register the
830 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800831 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700832 if (provisioned != mDeviceProvisioned) {
833 mDeviceProvisioned = provisioned;
834 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700835 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700836 }
837 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800838 }
839
Jim Millerbbf1a742012-07-17 18:30:30 -0700840 /**
841 * Handle {@link #MSG_DPM_STATE_CHANGED}
842 */
Jim Millerb0304762012-03-13 20:01:25 -0700843 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700844 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
845 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
846 if (cb != null) {
847 cb.onDevicePolicyManagerStateChanged();
848 }
Jim Millerb0304762012-03-13 20:01:25 -0700849 }
850 }
851
Jim Millerbbf1a742012-07-17 18:30:30 -0700852 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500853 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700854 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500855 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700856 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700857 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
858 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500859 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700860 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700861 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700862 try {
863 reply.sendResult(null);
864 } catch (RemoteException e) {
865 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700866 }
867
Jim Millerbbf1a742012-07-17 18:30:30 -0700868 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500869 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
870 */
871 protected void handleUserSwitchComplete(int userId) {
872 for (int i = 0; i < mCallbacks.size(); i++) {
873 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
874 if (cb != null) {
875 cb.onUserSwitchComplete(userId);
876 }
877 }
878 }
879
880 /**
Jim Miller90873d52013-09-26 18:11:38 -0700881 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
882 * keyguard crashes sometime after boot, then it will never receive this
883 * broadcast and hence not handle the event. This method is ultimately called by
884 * PhoneWindowManager in this case.
885 */
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100886 public void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700887 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -0700888 }
889
890 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800891 * Handle {@link #MSG_BOOT_COMPLETED}
892 */
893 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700894 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800895 mBootCompleted = true;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800896 for (int i = 0; i < mCallbacks.size(); i++) {
897 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
898 if (cb != null) {
899 cb.onBootCompleted();
900 }
901 }
902 }
903
904 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800905 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800906 * destroyed.
907 */
908 public boolean hasBootCompleted() {
909 return mBootCompleted;
910 }
911
912 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700913 * Handle {@link #MSG_DEVICE_PROVISIONED}
914 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700915 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700916 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700917 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
918 if (cb != null) {
919 cb.onDeviceProvisioned();
920 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700921 }
Michael Jurkafff56142012-11-28 16:51:00 -0800922 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700923 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800924 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
925 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700926 }
927 }
928
Jim Millerbbf1a742012-07-17 18:30:30 -0700929 /**
930 * Handle {@link #MSG_PHONE_STATE_CHANGED}
931 */
Jim Millerc23024d2010-02-24 15:37:00 -0800932 protected void handlePhoneStateChanged(String newState) {
933 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700934 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
935 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
936 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
937 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
938 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
939 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
940 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700941 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700942 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
943 if (cb != null) {
944 cb.onPhoneStateChanged(mPhoneState);
945 }
Jim Millerc23024d2010-02-24 15:37:00 -0800946 }
947 }
948
Jim Millerbbf1a742012-07-17 18:30:30 -0700949 /**
950 * Handle {@link #MSG_RINGER_MODE_CHANGED}
951 */
Jim Miller47088bb2009-11-24 00:40:16 -0800952 protected void handleRingerModeChange(int mode) {
953 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700954 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700955 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700956 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
957 if (cb != null) {
958 cb.onRingerModeChanged(mode);
959 }
Jim Miller47088bb2009-11-24 00:40:16 -0800960 }
961 }
962
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800963 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800964 * Handle {@link #MSG_TIME_UPDATE}
965 */
966 private void handleTimeUpdate() {
967 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700968 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700969 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
970 if (cb != null) {
971 cb.onTimeChanged();
972 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800973 }
974 }
975
976 /**
977 * Handle {@link #MSG_BATTERY_UPDATE}
978 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700979 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800980 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700981 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
982 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700983 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700984 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700985 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
986 if (cb != null) {
987 cb.onRefreshBatteryInfo(status);
988 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800989 }
990 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800991 }
992
993 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800994 * Handle {@link #MSG_SIM_STATE_CHANGE}
995 */
Jim Miller52a61332014-11-12 19:29:51 -0800996 private void handleSimStateChange(int subId, int slotId, State state) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800997
Jim Miller52a61332014-11-12 19:29:51 -0800998 if (DEBUG_SIM_STATES) {
999 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
1000 + slotId + ", state=" + state +")");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001001 }
1002
Wink Savillea54bf652014-12-11 13:37:50 -08001003 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Jim Miller52a61332014-11-12 19:29:51 -08001004 Log.w(TAG, "invalid subId in handleSimStateChange()");
1005 return;
1006 }
1007
1008 SimData data = mSimDatas.get(subId);
1009 final boolean changed;
1010 if (data == null) {
1011 data = new SimData(state, slotId, subId);
1012 mSimDatas.put(subId, data);
1013 changed = true; // no data yet; force update
1014 } else {
1015 changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
1016 data.simState = state;
1017 data.subId = subId;
1018 data.slotId = slotId;
1019 }
1020 if (changed && state != State.UNKNOWN) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001021 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001022 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1023 if (cb != null) {
Jim Miller52a61332014-11-12 19:29:51 -08001024 cb.onSimStateChanged(subId, slotId, state);
Jim Millerdcb3d842012-08-23 19:18:12 -07001025 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001026 }
1027 }
1028 }
1029
Jim Millerbbf1a742012-07-17 18:30:30 -07001030 /**
1031 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
1032 */
Jeff Sharkey054340d2011-09-01 22:28:03 -07001033 private void handleClockVisibilityChanged() {
1034 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
Jim Millerbbf1a742012-07-17 18:30:30 -07001035 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001036 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1037 if (cb != null) {
1038 cb.onClockVisibilityChanged();
1039 }
Jeff Sharkey054340d2011-09-01 22:28:03 -07001040 }
1041 }
1042
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001043 /**
1044 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
1045 */
1046 private void handleKeyguardVisibilityChanged(int showing) {
1047 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -04001048 boolean isShowing = (showing == 1);
1049 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001050 for (int i = 0; i < mCallbacks.size(); i++) {
1051 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1052 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -04001053 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001054 }
1055 }
1056 }
1057
Brian Colonna7fce3802013-09-17 15:51:32 -04001058 /**
Adrian Roosb6011622014-05-14 15:52:53 +02001059 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
1060 * @see #sendKeyguardBouncerChanged(boolean)
1061 */
1062 private void handleKeyguardBouncerChanged(int bouncer) {
1063 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
1064 boolean isBouncer = (bouncer == 1);
1065 mBouncer = isBouncer;
1066 for (int i = 0; i < mCallbacks.size(); i++) {
1067 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1068 if (cb != null) {
1069 cb.onKeyguardBouncerChanged(isBouncer);
1070 }
1071 }
1072 }
1073
1074 /**
Brian Colonna7fce3802013-09-17 15:51:32 -04001075 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
1076 */
1077 private void handleReportEmergencyCallAction() {
1078 for (int i = 0; i < mCallbacks.size(); i++) {
1079 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1080 if (cb != null) {
1081 cb.onEmergencyCallAction();
1082 }
1083 }
1084 }
1085
Danielle Millett5d2404d2012-11-01 00:05:27 -04001086 public boolean isKeyguardVisible() {
1087 return mKeyguardIsVisible;
1088 }
1089
Adrian Roosb6011622014-05-14 15:52:53 +02001090 /**
1091 * @return if the keyguard is currently in bouncer mode.
1092 */
1093 public boolean isKeyguardBouncer() {
1094 return mBouncer;
1095 }
1096
Brian Colonnaa5239892013-04-15 11:45:40 -04001097 public boolean isSwitchingUser() {
1098 return mSwitchingUser;
1099 }
1100
Jim Miller16464b82011-10-20 21:10:13 -07001101 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001102 final boolean nowPluggedIn = current.isPluggedIn();
1103 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -08001104 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -07001105 wasPluggedIn == true && nowPluggedIn == true
1106 && (old.status != current.status);
1107
1108 // change in plug state is always interesting
1109 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001110 return true;
1111 }
1112
1113 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -07001114 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001115 return true;
1116 }
1117
Jim Miller16464b82011-10-20 21:10:13 -07001118 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -07001119 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -07001120 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001121 }
1122 return false;
1123 }
1124
1125 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001126 * @return The default plmn (no service)
1127 */
1128 private CharSequence getDefaultPlmn() {
Jim Miller5ecd8112013-01-09 18:50:26 -08001129 return mContext.getResources().getText(R.string.keyguard_carrier_default);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001130 }
1131
1132 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001133 * Remove the given observer's callback.
1134 *
Jim Miller6212cc02012-09-05 17:35:31 -07001135 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001136 */
Jim Miller6212cc02012-09-05 17:35:31 -07001137 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1138 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1139 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1140 if (mCallbacks.get(i).get() == callback) {
1141 mCallbacks.remove(i);
1142 }
1143 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001144 }
1145
1146 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001147 * Register to receive notifications about general keyguard information
1148 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -07001149 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001150 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001151 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -07001152 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1153 // Prevent adding duplicate callbacks
1154 for (int i = 0; i < mCallbacks.size(); i++) {
1155 if (mCallbacks.get(i).get() == callback) {
1156 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1157 new Exception("Called by"));
1158 return;
Jim Millerdcb3d842012-08-23 19:18:12 -07001159 }
1160 }
Jim Miller6212cc02012-09-05 17:35:31 -07001161 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1162 removeCallback(null); // remove unused references
1163 sendUpdates(callback);
1164 }
1165
1166 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1167 // Notify listener of the current state
1168 callback.onRefreshBatteryInfo(mBatteryStatus);
1169 callback.onTimeChanged();
1170 callback.onRingerModeChanged(mRingMode);
1171 callback.onPhoneStateChanged(mPhoneState);
Jason Monk9ff69bd2014-12-02 16:43:17 -05001172 callback.onRefreshCarrierInfo();
Jim Miller6212cc02012-09-05 17:35:31 -07001173 callback.onClockVisibilityChanged();
Jim Miller52a61332014-11-12 19:29:51 -08001174 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
1175 final SimData state = data.getValue();
1176 callback.onSimStateChanged(state.subId, state.slotId, state.simState);
1177 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001178 }
1179
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001180 public void sendKeyguardVisibilityChanged(boolean showing) {
1181 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1182 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1183 message.arg1 = showing ? 1 : 0;
1184 message.sendToTarget();
1185 }
1186
Adrian Roosb6011622014-05-14 15:52:53 +02001187 /**
1188 * @see #handleKeyguardBouncerChanged(int)
1189 */
1190 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1191 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1192 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1193 message.arg1 = showingBouncer ? 1 : 0;
1194 message.sendToTarget();
1195 }
1196
Jeff Sharkey054340d2011-09-01 22:28:03 -07001197 public void reportClockVisible(boolean visible) {
1198 mClockVisible = visible;
1199 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
1200 }
1201
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001202 /**
Jim Miller90d5d462011-11-17 16:57:01 -08001203 * 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 -08001204 * have the information earlier than waiting for the intent
1205 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -08001206 *
1207 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1208 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001209 */
Jim Miller52a61332014-11-12 19:29:51 -08001210 public void reportSimUnlocked(int subId) {
1211 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
1212 int slotId = SubscriptionManager.getSlotId(subId);
1213 handleSimStateChange(subId, slotId, State.READY);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001214 }
1215
Brian Colonna7fce3802013-09-17 15:51:32 -04001216 /**
1217 * Report that the emergency call button has been pressed and the emergency dialer is
1218 * about to be displayed.
1219 *
1220 * @param bypassHandler runs immediately.
1221 *
1222 * NOTE: Must be called from UI thread if bypassHandler == true.
1223 */
1224 public void reportEmergencyCallAction(boolean bypassHandler) {
1225 if (!bypassHandler) {
1226 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1227 } else {
1228 handleReportEmergencyCallAction();
1229 }
1230 }
1231
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001232 /**
1233 * @return Whether the device is provisioned (whether they have gone through
1234 * the setup wizard)
1235 */
1236 public boolean isDeviceProvisioned() {
1237 return mDeviceProvisioned;
1238 }
1239
Jim Miller258341c2012-08-30 16:50:10 -07001240 public int getFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001241 return mFailedAttempts;
1242 }
1243
Jim Miller258341c2012-08-30 16:50:10 -07001244 public void clearFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001245 mFailedAttempts = 0;
1246 }
1247
Jim Millerf41fc962014-06-18 16:33:51 -07001248 public void clearFingerprintRecognized() {
Jim Miller9f0753f2015-03-23 23:59:22 -07001249 mUserFingerprintAuthenticated.clear();
Jim Millerf41fc962014-06-18 16:33:51 -07001250 }
1251
Jim Miller258341c2012-08-30 16:50:10 -07001252 public void reportFailedUnlockAttempt() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001253 mFailedAttempts++;
1254 }
Jim Miller1c188282011-08-08 22:27:58 -07001255
Jeff Sharkey054340d2011-09-01 22:28:03 -07001256 public boolean isClockVisible() {
1257 return mClockVisible;
1258 }
1259
Brian Colonna267cb2b2011-09-26 13:52:25 -04001260 public int getPhoneState() {
1261 return mPhoneState;
1262 }
Steven Rossb9430d22011-11-23 07:54:09 -05001263
Jim Miller52a61332014-11-12 19:29:51 -08001264 public boolean isSimPinVoiceSecure() {
1265 // TODO: only count SIMs that handle voice
1266 return isSimPinSecure();
Jim Millerdcb3d842012-08-23 19:18:12 -07001267 }
1268
1269 public boolean isSimPinSecure() {
Jim Miller52a61332014-11-12 19:29:51 -08001270 // True if any SIM is pin secure
1271 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
1272 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
1273 }
1274 return false;
1275 }
1276
Jason Monk9ff69bd2014-12-02 16:43:17 -05001277 public State getSimState(int subId) {
Jim Miller52a61332014-11-12 19:29:51 -08001278 if (mSimDatas.containsKey(subId)) {
1279 return mSimDatas.get(subId).simState;
1280 } else {
1281 return State.UNKNOWN;
1282 }
1283 }
1284
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001285 /**
1286 * @return true if and only if the state has changed for the specified {@code slotId}
1287 */
1288 private boolean refreshSimState(int subId, int slotId) {
Jim Miller52a61332014-11-12 19:29:51 -08001289
1290 // This is awful. It exists because there are two APIs for getting the SIM status
1291 // that don't return the complete set of values and have different types. In Keyguard we
1292 // need IccCardConstants, but TelephonyManager would only give us
1293 // TelephonyManager.SIM_STATE*, so we retrieve it manually.
xinhe18b9c3c2014-12-02 15:03:20 -08001294 final TelephonyManager tele = TelephonyManager.from(mContext);
1295 int simState = tele.getSimState(slotId);
Jim Miller52a61332014-11-12 19:29:51 -08001296 State state;
1297 try {
xinhe18b9c3c2014-12-02 15:03:20 -08001298 state = State.intToState(simState);
Jim Miller52a61332014-11-12 19:29:51 -08001299 } catch(IllegalArgumentException ex) {
xinhe18b9c3c2014-12-02 15:03:20 -08001300 Log.w(TAG, "Unknown sim state: " + simState);
Jim Miller52a61332014-11-12 19:29:51 -08001301 state = State.UNKNOWN;
John Spurlock5b13e922015-01-07 11:04:58 -05001302 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001303 SimData data = mSimDatas.get(subId);
1304 final boolean changed;
1305 if (data == null) {
1306 data = new SimData(state, slotId, subId);
1307 mSimDatas.put(subId, data);
1308 changed = true; // no data yet; force update
1309 } else {
1310 changed = data.simState != state;
1311 data.simState = state;
1312 }
1313 return changed;
Jim Millerdcb3d842012-08-23 19:18:12 -07001314 }
1315
1316 public static boolean isSimPinSecure(IccCardConstants.State state) {
1317 final IccCardConstants.State simState = state;
1318 return (simState == IccCardConstants.State.PIN_REQUIRED
1319 || simState == IccCardConstants.State.PUK_REQUIRED
1320 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001321 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001322
1323 public DisplayClientState getCachedDisplayClientState() {
1324 return mDisplayClientState;
1325 }
Jim Miller20daffd2013-10-07 14:59:53 -07001326
1327 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1328 // (KeyguardViewMediator, KeyguardHostView)
1329 public void dispatchScreenTurnedOn() {
1330 synchronized (this) {
1331 mScreenOn = true;
1332 }
1333 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1334 }
1335
John Spurlock36a13422015-03-24 21:15:48 -04001336 public void dispatchScreenTurnedOff(int why) {
Jim Miller20daffd2013-10-07 14:59:53 -07001337 synchronized(this) {
1338 mScreenOn = false;
1339 }
1340 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1341 }
1342
1343 public boolean isScreenOn() {
1344 return mScreenOn;
1345 }
Jim Miller52a61332014-11-12 19:29:51 -08001346
1347 /**
1348 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
1349 * @param state
Wink Savilled09c4ca2014-11-22 10:08:16 -08001350 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
Jim Miller52a61332014-11-12 19:29:51 -08001351 */
1352 public int getNextSubIdForState(State state) {
1353 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
Wink Savilled09c4ca2014-11-22 10:08:16 -08001354 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Jim Miller52a61332014-11-12 19:29:51 -08001355 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
1356 for (int i = 0; i < list.size(); i++) {
1357 final SubscriptionInfo info = list.get(i);
1358 final int id = info.getSubscriptionId();
1359 int slotId = SubscriptionManager.getSlotId(id);
1360 if (state == getSimState(id) && bestSlotId > slotId ) {
1361 resultId = id;
1362 bestSlotId = slotId;
1363 }
1364 }
1365 return resultId;
1366 }
1367
1368 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) {
1369 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
1370 for (int i = 0; i < list.size(); i++) {
1371 SubscriptionInfo info = list.get(i);
1372 if (subId == info.getSubscriptionId()) return info;
1373 }
1374 return null; // not found
1375 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001376}