blob: 3c30d8c4840cc5e5f8aa0e68b039b81ce3425aa8 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080018
Jorim Jaggiccdfa932015-04-13 16:29:48 -070019import android.app.ActivityManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070020import android.app.ActivityManagerNative;
Jorim Jaggic7dea6e2014-07-26 14:36:57 +020021import android.app.AlarmManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070022import android.app.IUserSwitchObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070023import android.app.PendingIntent;
Jim Millerb0304762012-03-13 20:01:25 -070024import android.app.admin.DevicePolicyManager;
Adrian Roos46842d92014-03-27 14:58:03 +010025import android.app.trust.TrustManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080026import android.content.BroadcastReceiver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080030import android.database.ContentObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070031import android.graphics.Bitmap;
32
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080033import static android.os.BatteryManager.BATTERY_STATUS_FULL;
34import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
Jim Miller16464b82011-10-20 21:10:13 -070035import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
36import static android.os.BatteryManager.EXTRA_STATUS;
37import static android.os.BatteryManager.EXTRA_PLUGGED;
38import static android.os.BatteryManager.EXTRA_LEVEL;
39import static android.os.BatteryManager.EXTRA_HEALTH;
Jim Miller06e34502014-07-17 14:46:05 -070040
Jim Miller47088bb2009-11-24 00:40:16 -080041import android.media.AudioManager;
Jim Miller79a444a2011-02-15 15:02:11 -080042import android.os.BatteryManager;
Jim Miller9f0753f2015-03-23 23:59:22 -070043import android.os.CancellationSignal;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080044import android.os.Handler;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070045import android.os.IRemoteCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080046import android.os.Message;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070047import android.os.RemoteException;
Amith Yamasanie8e93a12013-05-09 18:12:30 -070048import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080049import android.provider.Settings;
Dianne Hackbornb7e787f2009-05-07 15:55:42 -070050
Wink Savillea639b312012-07-10 12:37:54 -070051import com.android.internal.telephony.IccCardConstants;
Jim Miller52a61332014-11-12 19:29:51 -080052import com.android.internal.telephony.IccCardConstants.State;
53import com.android.internal.telephony.PhoneConstants;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080054import com.android.internal.telephony.TelephonyIntents;
Jim Miller9f0753f2015-03-23 23:59:22 -070055
Jim Millerebbf2052015-03-31 17:24:34 -070056import android.hardware.fingerprint.FingerprintManager;
57import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
Jim Millerebbf2052015-03-31 17:24:34 -070058import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
Jim Miller52a61332014-11-12 19:29:51 -080059import android.telephony.SubscriptionInfo;
Jim Miller52a61332014-11-12 19:29:51 -080060import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080061import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Jim Millerc23024d2010-02-24 15:37:00 -080062import android.telephony.TelephonyManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080063import android.util.Log;
Adrian Roos46842d92014-03-27 14:58:03 +010064import android.util.SparseBooleanArray;
Jorim Jaggi9f743032015-05-04 15:22:40 -070065import android.util.SparseIntArray;
Adrian Roos46842d92014-03-27 14:58:03 +010066
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080067import com.google.android.collect.Lists;
68
Jim Millerdcb3d842012-08-23 19:18:12 -070069import java.lang.ref.WeakReference;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080070import java.util.ArrayList;
Jim Miller52a61332014-11-12 19:29:51 -080071import java.util.HashMap;
72import java.util.List;
73import java.util.Map.Entry;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080074
75/**
76 * Watches for updates that may be interesting to the keyguard, and provides
77 * the up to date information as well as a registration for callbacks that care
78 * to be updated.
79 *
80 * Note: under time crunch, this has been extended to include some stuff that
81 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
Jim Miller258341c2012-08-30 16:50:10 -070082 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
83 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080084 */
Adrian Roos46842d92014-03-27 14:58:03 +010085public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080086
Jim Millerbbf1a742012-07-17 18:30:30 -070087 private static final String TAG = "KeyguardUpdateMonitor";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010088 private static final boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller52a61332014-11-12 19:29:51 -080089 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
Jim Millerbbf1a742012-07-17 18:30:30 -070090 private static final int LOW_BATTERY_THRESHOLD = 20;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080091
Jorim Jaggie7b12522014-08-06 16:41:21 +020092 private static final String ACTION_FACE_UNLOCK_STARTED
93 = "com.android.facelock.FACE_UNLOCK_STARTED";
94 private static final String ACTION_FACE_UNLOCK_STOPPED
95 = "com.android.facelock.FACE_UNLOCK_STOPPED";
96
Jim Millerbbf1a742012-07-17 18:30:30 -070097 // Callback messages
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080098 private static final int MSG_TIME_UPDATE = 301;
99 private static final int MSG_BATTERY_UPDATE = 302;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800100 private static final int MSG_SIM_STATE_CHANGE = 304;
Jim Miller47088bb2009-11-24 00:40:16 -0800101 private static final int MSG_RINGER_MODE_CHANGED = 305;
Jim Millerc23024d2010-02-24 15:37:00 -0800102 private static final int MSG_PHONE_STATE_CHANGED = 306;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700103 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -0700104 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500105 private static final int MSG_USER_SWITCHING = 310;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400106 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
Jim Millerf41fc962014-06-18 16:33:51 -0700107 private static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500108 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Millerf41fc962014-06-18 16:33:51 -0700109 private static final int MSG_USER_INFO_CHANGED = 317;
110 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jim Miller20daffd2013-10-07 14:59:53 -0700111 private static final int MSG_SCREEN_TURNED_ON = 319;
112 private static final int MSG_SCREEN_TURNED_OFF = 320;
Adrian Roosb6011622014-05-14 15:52:53 +0200113 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
Jim Miller9f0753f2015-03-23 23:59:22 -0700114 private static final int MSG_FINGERPRINT_AUTHENTICATED = 323;
115 private static final int MSG_FINGERPRINT_ERROR = 324;
116 private static final int MSG_FINGERPRINT_HELP = 325;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700117 private static final int MSG_FINGERPRINT_AUTH_FAILED = 326;
118 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327;
119 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800120
Jim Millerdcb3d842012-08-23 19:18:12 -0700121 private static KeyguardUpdateMonitor sInstance;
122
Jim Millerbbf1a742012-07-17 18:30:30 -0700123 private final Context mContext;
Jim Miller52a61332014-11-12 19:29:51 -0800124 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
Jim Millerbbf1a742012-07-17 18:30:30 -0700125
Jim Millerbbf1a742012-07-17 18:30:30 -0700126 private int mRingMode;
127 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400128 private boolean mKeyguardIsVisible;
Adrian Roosb6011622014-05-14 15:52:53 +0200129 private boolean mBouncer;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800130 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700131
Jim Millerdcb3d842012-08-23 19:18:12 -0700132 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700133 private boolean mDeviceProvisioned;
134
Jim Millerdcb3d842012-08-23 19:18:12 -0700135 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700136 private BatteryStatus mBatteryStatus;
137
Jim Millerdcb3d842012-08-23 19:18:12 -0700138 // Password attempts
Jorim Jaggi9f743032015-05-04 15:22:40 -0700139 private SparseIntArray mFailedAttempts = new SparseIntArray();
Brian Colonnacc4104f2012-10-09 17:50:46 -0400140
Jim Millerbbf1a742012-07-17 18:30:30 -0700141 private boolean mClockVisible;
142
Jim Miller6212cc02012-09-05 17:35:31 -0700143 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700144 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800145 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700146
Brian Colonnaa5239892013-04-15 11:45:40 -0400147 private boolean mSwitchingUser;
148
Jim Miller20daffd2013-10-07 14:59:53 -0700149 private boolean mScreenOn;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800150 private SubscriptionManager mSubscriptionManager;
151 private List<SubscriptionInfo> mSubscriptionInfo;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700152 private boolean mFingerprintDetectionRunning;
Jorim Jaggi237b0612015-05-01 14:28:49 -0700153 private TrustManager mTrustManager;
Jim Miller20daffd2013-10-07 14:59:53 -0700154
Jim Millerbbf1a742012-07-17 18:30:30 -0700155 private final Handler mHandler = new Handler() {
156 @Override
157 public void handleMessage(Message msg) {
158 switch (msg.what) {
159 case MSG_TIME_UPDATE:
160 handleTimeUpdate();
161 break;
162 case MSG_BATTERY_UPDATE:
163 handleBatteryUpdate((BatteryStatus) msg.obj);
164 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700165 case MSG_SIM_STATE_CHANGE:
Jim Miller52a61332014-11-12 19:29:51 -0800166 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700167 break;
168 case MSG_RINGER_MODE_CHANGED:
169 handleRingerModeChange(msg.arg1);
170 break;
171 case MSG_PHONE_STATE_CHANGED:
Adrian Roosb6011622014-05-14 15:52:53 +0200172 handlePhoneStateChanged((String) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700173 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700174 case MSG_DEVICE_PROVISIONED:
175 handleDeviceProvisioned();
176 break;
177 case MSG_DPM_STATE_CHANGED:
178 handleDevicePolicyManagerStateChanged();
179 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500180 case MSG_USER_SWITCHING:
Adrian Roosb6011622014-05-14 15:52:53 +0200181 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
Chris Wrenf41c61b2012-11-29 15:19:54 -0500182 break;
183 case MSG_USER_SWITCH_COMPLETE:
184 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700185 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400186 case MSG_KEYGUARD_VISIBILITY_CHANGED:
187 handleKeyguardVisibilityChanged(msg.arg1);
188 break;
Adrian Roosb6011622014-05-14 15:52:53 +0200189 case MSG_KEYGUARD_BOUNCER_CHANGED:
190 handleKeyguardBouncerChanged(msg.arg1);
191 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800192 case MSG_BOOT_COMPLETED:
193 handleBootCompleted();
194 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700195 case MSG_USER_INFO_CHANGED:
196 handleUserInfoChanged(msg.arg1);
197 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400198 case MSG_REPORT_EMERGENCY_CALL_ACTION:
199 handleReportEmergencyCallAction();
200 break;
Jim Miller20daffd2013-10-07 14:59:53 -0700201 case MSG_SCREEN_TURNED_OFF:
202 handleScreenTurnedOff(msg.arg1);
203 break;
204 case MSG_SCREEN_TURNED_ON:
205 handleScreenTurnedOn();
206 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700207 case MSG_FINGERPRINT_AUTHENTICATED:
208 handleFingerprintAuthenticated(msg.arg1, msg.arg2);
Jim Millerf41fc962014-06-18 16:33:51 -0700209 break;
Jim Miller9f0753f2015-03-23 23:59:22 -0700210 case MSG_FINGERPRINT_HELP:
211 handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
212 break;
213 case MSG_FINGERPRINT_ERROR:
214 handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
Jim Millerf41fc962014-06-18 16:33:51 -0700215 break;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700216 case MSG_FINGERPRINT_AUTH_FAILED:
217 handleFingerprintAuthFailed();
218 break;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200219 case MSG_FACE_UNLOCK_STATE_CHANGED:
Adrian Roos4a410172014-08-20 17:41:44 +0200220 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200221 break;
Jim Miller52a61332014-11-12 19:29:51 -0800222 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED:
223 handleSimSubscriptionInfoChanged();
224 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700225 }
226 }
227 };
228
Wink Savilled09c4ca2014-11-22 10:08:16 -0800229 private OnSubscriptionsChangedListener mSubscriptionListener =
230 new OnSubscriptionsChangedListener() {
Jim Miller52a61332014-11-12 19:29:51 -0800231 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800232 public void onSubscriptionsChanged() {
Jim Miller52a61332014-11-12 19:29:51 -0800233 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
234 }
235 };
236
Adrian Roos46842d92014-03-27 14:58:03 +0100237 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
Adrian Roos7861c662014-07-25 15:37:28 +0200238 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
Jim Miller9f0753f2015-03-23 23:59:22 -0700239 private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
Adrian Roos4a410172014-08-20 17:41:44 +0200240 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
Adrian Roos46842d92014-03-27 14:58:03 +0100241
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700242 private static int sCurrentUser;
243
244 public synchronized static void setCurrentUser(int currentUser) {
245 sCurrentUser = currentUser;
246 }
247
248 public synchronized static int getCurrentUser() {
249 return sCurrentUser;
250 }
251
Adrian Roos46842d92014-03-27 14:58:03 +0100252 @Override
Adrian Roos94e15a52015-04-16 12:23:18 -0700253 public void onTrustChanged(boolean enabled, int userId, int flags) {
Adrian Roos46842d92014-03-27 14:58:03 +0100254 mUserHasTrust.put(userId, enabled);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200255 for (int i = 0; i < mCallbacks.size(); i++) {
256 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
257 if (cb != null) {
258 cb.onTrustChanged(userId);
Adrian Roos94e15a52015-04-16 12:23:18 -0700259 if (enabled && flags != 0) {
260 cb.onTrustGrantedWithFlags(flags, userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200261 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200262 }
263 }
Adrian Roos46842d92014-03-27 14:58:03 +0100264 }
265
Jim Miller52a61332014-11-12 19:29:51 -0800266 protected void handleSimSubscriptionInfoChanged() {
267 if (DEBUG_SIM_STATES) {
268 Log.v(TAG, "onSubscriptionInfoChanged()");
Wink Savilled09c4ca2014-11-22 10:08:16 -0800269 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
270 if (sil != null) {
271 for (SubscriptionInfo subInfo : sil) {
272 Log.v(TAG, "SubInfo:" + subInfo);
273 }
274 } else {
275 Log.v(TAG, "onSubscriptionInfoChanged: list is null");
Jim Miller52a61332014-11-12 19:29:51 -0800276 }
277 }
278 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
279
280 // Hack level over 9000: Because the subscription id is not yet valid when we see the
281 // first update in handleSimStateChange, we need to force refresh all all SIM states
282 // so the subscription id for them is consistent.
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100283 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
Jim Miller52a61332014-11-12 19:29:51 -0800284 for (int i = 0; i < subscriptionInfos.size(); i++) {
285 SubscriptionInfo info = subscriptionInfos.get(i);
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100286 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
287 if (changed) {
288 changedSubscriptions.add(info);
289 }
Jim Miller52a61332014-11-12 19:29:51 -0800290 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +0100291 for (int i = 0; i < changedSubscriptions.size(); i++) {
292 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
Jim Miller52a61332014-11-12 19:29:51 -0800293 for (int j = 0; j < mCallbacks.size(); j++) {
294 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
295 if (cb != null) {
296 cb.onSimStateChanged(data.subId, data.slotId, data.simState);
297 }
298 }
299 }
Jason Monk6c985dc2015-01-09 16:07:14 -0500300 for (int j = 0; j < mCallbacks.size(); j++) {
301 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
302 if (cb != null) {
303 cb.onRefreshCarrierInfo();
304 }
305 }
Jim Miller52a61332014-11-12 19:29:51 -0800306 }
307
Wink Savilled09c4ca2014-11-22 10:08:16 -0800308 /** @return List of SubscriptionInfo records, maybe empty but never null */
Jim Miller52a61332014-11-12 19:29:51 -0800309 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
Wink Savilled09c4ca2014-11-22 10:08:16 -0800310 List<SubscriptionInfo> sil = mSubscriptionInfo;
311 if (sil == null || forceReload) {
312 sil = mSubscriptionManager.getActiveSubscriptionInfoList();
313 }
314 if (sil == null) {
315 // getActiveSubscriptionInfoList was null callers expect an empty list.
316 mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
317 } else {
318 mSubscriptionInfo = sil;
Jim Miller52a61332014-11-12 19:29:51 -0800319 }
320 return mSubscriptionInfo;
321 }
322
Adrian Roos7861c662014-07-25 15:37:28 +0200323 @Override
324 public void onTrustManagedChanged(boolean managed, int userId) {
325 mUserTrustIsManaged.put(userId, managed);
326
327 for (int i = 0; i < mCallbacks.size(); i++) {
328 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
329 if (cb != null) {
330 cb.onTrustManagedChanged(userId);
331 }
332 }
333 }
334
Jim Miller9f0753f2015-03-23 23:59:22 -0700335 private void onFingerprintAuthenticated(int userId) {
336 mUserFingerprintAuthenticated.put(userId, true);
Jim Millerf41fc962014-06-18 16:33:51 -0700337 for (int i = 0; i < mCallbacks.size(); i++) {
338 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
339 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700340 cb.onFingerprintAuthenticated(userId);
Jim Millerf41fc962014-06-18 16:33:51 -0700341 }
342 }
343 }
344
Jim Millerce7eb6d2015-04-03 19:29:13 -0700345 private void handleFingerprintAuthFailed() {
346 // FingerprintManager will allow us to retry a few times before finally giving up.
347 // TODO: Figure out the proper logic to stop this call when max tries is reached.
348 handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
349 }
Jim Millerf41fc962014-06-18 16:33:51 -0700350
Jim Millerce7eb6d2015-04-03 19:29:13 -0700351 private void handleFingerprintAuthenticated(int fingerId, int groupId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700352 try {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700353 final int userId;
354 try {
355 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
356 } catch (RemoteException e) {
357 Log.e(TAG, "Failed to get current user id: ", e);
358 return;
Jim Millerf41fc962014-06-18 16:33:51 -0700359 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700360 if (isFingerprintDisabled(userId)) {
361 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
362 return;
363 }
Jim Millerbe675422015-05-11 20:45:25 -0700364 onFingerprintAuthenticated(userId);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700365 } finally {
366 setFingerprintRunningDetectionRunning(false);
Jim Millerf41fc962014-06-18 16:33:51 -0700367 }
368 }
369
Jim Miller9f0753f2015-03-23 23:59:22 -0700370 private void handleFingerprintHelp(int msgId, String helpString) {
Jim Millerf41fc962014-06-18 16:33:51 -0700371 for (int i = 0; i < mCallbacks.size(); i++) {
372 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
373 if (cb != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700374 cb.onFingerprintHelp(msgId, helpString);
375 }
376 }
377 }
378
379 private void handleFingerprintError(int msgId, String errString) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700380 setFingerprintRunningDetectionRunning(false);
Jim Miller9f0753f2015-03-23 23:59:22 -0700381 for (int i = 0; i < mCallbacks.size(); i++) {
382 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
383 if (cb != null) {
384 cb.onFingerprintError(msgId, errString);
Jim Millerf41fc962014-06-18 16:33:51 -0700385 }
386 }
387 }
388
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700389 private void setFingerprintRunningDetectionRunning(boolean running) {
390 if (running != mFingerprintDetectionRunning) {
391 mFingerprintDetectionRunning = running;
392 notifyFingerprintRunningStateChanged();
393 }
394 }
395
396 private void notifyFingerprintRunningStateChanged() {
397 for (int i = 0; i < mCallbacks.size(); i++) {
398 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
399 if (cb != null) {
400 cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
401 }
402 }
403 }
Adrian Roos4a410172014-08-20 17:41:44 +0200404 private void handleFaceUnlockStateChanged(boolean running, int userId) {
405 mUserFaceUnlockRunning.put(userId, running);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200406 for (int i = 0; i < mCallbacks.size(); i++) {
407 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
408 if (cb != null) {
Adrian Roos4a410172014-08-20 17:41:44 +0200409 cb.onFaceUnlockStateChanged(running, userId);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200410 }
411 }
412 }
413
Adrian Roos4a410172014-08-20 17:41:44 +0200414 public boolean isFaceUnlockRunning(int userId) {
415 return mUserFaceUnlockRunning.get(userId);
416 }
417
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700418 public boolean isFingerprintDetectionRunning() {
419 return mFingerprintDetectionRunning;
420 }
421
Jim Miller50e62182014-04-23 17:25:00 -0700422 private boolean isTrustDisabled(int userId) {
Adrian Roosa4da9f62015-02-21 01:15:21 +0100423 // Don't allow trust agent if device is secured with a SIM PIN. This is here
424 // mainly because there's no other way to prompt the user to enter their SIM PIN
425 // once they get past the keyguard screen.
426 final boolean disabledBySimPin = isSimPinSecure();
427 return disabledBySimPin;
Jim Miller50e62182014-04-23 17:25:00 -0700428 }
429
Jim Miller06e34502014-07-17 14:46:05 -0700430 private boolean isFingerprintDisabled(int userId) {
431 final DevicePolicyManager dpm =
432 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
433 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
434 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
435 }
436
Adrian Roos46842d92014-03-27 14:58:03 +0100437 public boolean getUserHasTrust(int userId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700438 return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
Jim Miller9f0753f2015-03-23 23:59:22 -0700439 || mUserFingerprintAuthenticated.get(userId);
Adrian Roos46842d92014-03-27 14:58:03 +0100440 }
441
Adrian Roos7861c662014-07-25 15:37:28 +0200442 public boolean getUserTrustIsManaged(int userId) {
443 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
444 }
445
Jim Miller8f09fd22013-03-14 19:04:28 -0700446 static class DisplayClientState {
447 public int clientGeneration;
448 public boolean clearing;
449 public PendingIntent intent;
450 public int playbackState;
451 public long playbackEventTime;
452 }
453
454 private DisplayClientState mDisplayClientState = new DisplayClientState();
455
Jim Millerbbf1a742012-07-17 18:30:30 -0700456 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
457
458 public void onReceive(Context context, Intent intent) {
459 final String action = intent.getAction();
460 if (DEBUG) Log.d(TAG, "received broadcast " + action);
461
462 if (Intent.ACTION_TIME_TICK.equals(action)
463 || Intent.ACTION_TIME_CHANGED.equals(action)
Adrian Roos48c796c2014-09-01 14:59:23 +0200464 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700465 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700466 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
467 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
468 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
469 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
470 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
471 final Message msg = mHandler.obtainMessage(
472 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
473 mHandler.sendMessage(msg);
474 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller52a61332014-11-12 19:29:51 -0800475 SimData args = SimData.fromIntent(intent);
Jim Millerbbf1a742012-07-17 18:30:30 -0700476 if (DEBUG_SIM_STATES) {
Jim Miller52a61332014-11-12 19:29:51 -0800477 Log.v(TAG, "action " + action
478 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
479 + " slotId: " + args.slotId + " subid: " + args.subId);
Jim Millerbbf1a742012-07-17 18:30:30 -0700480 }
Jim Miller52a61332014-11-12 19:29:51 -0800481 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
482 .sendToTarget();
Jim Millerbbf1a742012-07-17 18:30:30 -0700483 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
484 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
485 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
486 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
487 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
488 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800489 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700490 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700491 }
492 }
493 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700494
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700495 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
496
497 public void onReceive(Context context, Intent intent) {
498 final String action = intent.getAction();
Adrian Roos48c796c2014-09-01 14:59:23 +0200499 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
500 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
501 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700502 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
503 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
Adrian Roos48c796c2014-09-01 14:59:23 +0200504 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
505 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
506 getSendingUserId()));
507 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
508 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
509 getSendingUserId()));
510 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
511 .equals(action)) {
512 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700513 }
514 }
515 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700516
517 private FingerprintManager.AuthenticationCallback mAuthenticationCallback
518 = new AuthenticationCallback() {
Jim Millerf41fc962014-06-18 16:33:51 -0700519
520 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700521 public void onAuthenticationFailed() {
522 mHandler.obtainMessage(MSG_FINGERPRINT_AUTH_FAILED).sendToTarget();
523 };
524
525 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700526 public void onAuthenticationSucceeded(AuthenticationResult result) {
527 mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED,
528 result.getFingerprint().getFingerId(),
529 result.getFingerprint().getGroupId()).sendToTarget();
Jim Millerf41fc962014-06-18 16:33:51 -0700530 }
531
532 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700533 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
534 mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget();
535 }
536
537 @Override
538 public void onAuthenticationError(int errMsgId, CharSequence errString) {
Jorim Jaggi570de1e2015-05-01 15:08:34 -0700539 mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString).sendToTarget();
Jim Millerf41fc962014-06-18 16:33:51 -0700540 }
541 };
Jim Miller9f0753f2015-03-23 23:59:22 -0700542 private CancellationSignal mFingerprintCancelSignal;
543 private FingerprintManager mFpm;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700544
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800545 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800546 * When we receive a
547 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700548 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800549 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800550 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800551 */
Jim Miller52a61332014-11-12 19:29:51 -0800552 private static class SimData {
553 public State simState;
554 public int slotId;
555 public int subId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800556
Jim Miller52a61332014-11-12 19:29:51 -0800557 SimData(State state, int slot, int id) {
Jim Miller90d5d462011-11-17 16:57:01 -0800558 simState = state;
Jim Miller52a61332014-11-12 19:29:51 -0800559 slotId = slot;
560 subId = id;
Jim Miller90d5d462011-11-17 16:57:01 -0800561 }
562
Jim Miller52a61332014-11-12 19:29:51 -0800563 static SimData fromIntent(Intent intent) {
564 State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800565 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
566 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
567 }
Wink Savillea639b312012-07-10 12:37:54 -0700568 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
Jim Miller52a61332014-11-12 19:29:51 -0800569 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
570 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
Wink Savilled09c4ca2014-11-22 10:08:16 -0800571 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea639b312012-07-10 12:37:54 -0700572 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700573 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700574 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700575
Wink Savillea639b312012-07-10 12:37:54 -0700576 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700577 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700578 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700579 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700580 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700581 }
Wink Savillea639b312012-07-10 12:37:54 -0700582 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
583 state = IccCardConstants.State.READY;
584 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800585 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700586 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
587 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
588 state = IccCardConstants.State.PIN_REQUIRED;
589 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
590 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800591 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700592 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800593 }
Wink Savillea639b312012-07-10 12:37:54 -0700594 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
595 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700596 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
597 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
598 // This is required because telephony doesn't return to "READY" after
599 // these state transitions. See bug 7197471.
600 state = IccCardConstants.State.READY;
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 }
Jim Miller52a61332014-11-12 19:29:51 -0800604 return new SimData(state, slotId, subId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800605 }
606
607 public String toString() {
Jim Miller52a61332014-11-12 19:29:51 -0800608 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800609 }
610 }
611
Adrian Roos12c1ef52014-06-04 13:54:08 +0200612 public static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700613 public final int status;
614 public final int level;
615 public final int plugged;
616 public final int health;
617 public BatteryStatus(int status, int level, int plugged, int health) {
618 this.status = status;
619 this.level = level;
620 this.plugged = plugged;
621 this.health = health;
622 }
623
Jim Millerbbf1a742012-07-17 18:30:30 -0700624 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700625 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700626 * @return true if the device is plugged in.
627 */
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100628 public boolean isPluggedIn() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700629 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700630 || plugged == BatteryManager.BATTERY_PLUGGED_USB
631 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700632 }
633
634 /**
635 * Whether or not the device is charged. Note that some devices never return 100% for
636 * battery level, so this allows either battery level or status to determine if the
637 * battery is charged.
638 * @return true if the device is charged
639 */
640 public boolean isCharged() {
641 return status == BATTERY_STATUS_FULL || level >= 100;
642 }
643
644 /**
645 * Whether battery is low and needs to be charged.
646 * @return true if battery is low
647 */
648 public boolean isBatteryLow() {
649 return level < LOW_BATTERY_THRESHOLD;
650 }
651
Jim Miller16464b82011-10-20 21:10:13 -0700652 }
653
Jim Millerdcb3d842012-08-23 19:18:12 -0700654 public static KeyguardUpdateMonitor getInstance(Context context) {
655 if (sInstance == null) {
656 sInstance = new KeyguardUpdateMonitor(context);
657 }
658 return sInstance;
659 }
660
Jim Miller20daffd2013-10-07 14:59:53 -0700661 protected void handleScreenTurnedOn() {
Jorim Jaggi864e64b2015-05-20 14:13:23 -0700662 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700663 final int count = mCallbacks.size();
664 for (int i = 0; i < count; i++) {
665 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
666 if (cb != null) {
667 cb.onScreenTurnedOn();
668 }
669 }
670 }
671
672 protected void handleScreenTurnedOff(int arg1) {
Jim Millerf41fc962014-06-18 16:33:51 -0700673 clearFingerprintRecognized();
Jim Miller20daffd2013-10-07 14:59:53 -0700674 final int count = mCallbacks.size();
675 for (int i = 0; i < count; i++) {
676 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
677 if (cb != null) {
678 cb.onScreenTurnedOff(arg1);
679 }
680 }
Jorim Jaggiea657062015-04-28 13:45:11 -0700681 updateFingerprintListeningState();
Jim Miller20daffd2013-10-07 14:59:53 -0700682 }
683
Adam Powell43a372f2013-09-27 17:43:53 -0700684 /**
685 * IMPORTANT: Must be called from UI thread.
686 */
687 public void dispatchSetBackground(Bitmap bmp) {
688 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
689 final int count = mCallbacks.size();
690 for (int i = 0; i < count; i++) {
691 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
692 if (cb != null) {
693 cb.onSetBackground(bmp);
694 }
695 }
696 }
697
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700698 private void handleUserInfoChanged(int userId) {
699 for (int i = 0; i < mCallbacks.size(); i++) {
700 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
701 if (cb != null) {
702 cb.onUserInfoChanged(userId);
703 }
704 }
705 }
706
Jim Millerdcb3d842012-08-23 19:18:12 -0700707 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800708 mContext = context;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800709 mSubscriptionManager = SubscriptionManager.from(context);
Michael Jurkafff56142012-11-28 16:51:00 -0800710 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800711 // Since device can't be un-provisioned, we only need to register a content observer
712 // to update mDeviceProvisioned when we are...
713 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700714 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800715 }
Jim Miller47088bb2009-11-24 00:40:16 -0800716
Jim Millerbbf1a742012-07-17 18:30:30 -0700717 // Take a guess at initial SIM state, battery status and PLMN until we get an update
Jim Miller16464b82011-10-20 21:10:13 -0700718 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800719
Jim Millerbbf1a742012-07-17 18:30:30 -0700720 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800721 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800722 filter.addAction(Intent.ACTION_TIME_TICK);
723 filter.addAction(Intent.ACTION_TIME_CHANGED);
724 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
725 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
726 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800727 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Jim Miller47088bb2009-11-24 00:40:16 -0800728 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerbbf1a742012-07-17 18:30:30 -0700729 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700730
Adam Cohenc276e822012-11-08 13:01:08 -0800731 final IntentFilter bootCompleteFilter = new IntentFilter();
732 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
733 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
734 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
735
Adrian Roos48c796c2014-09-01 14:59:23 +0200736 final IntentFilter allUserFilter = new IntentFilter();
737 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
738 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
739 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
740 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
741 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
742 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700743 null, null);
744
Wink Saville071743f2015-01-12 17:11:04 -0800745 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700746 try {
747 ActivityManagerNative.getDefault().registerUserSwitchObserver(
748 new IUserSwitchObserver.Stub() {
749 @Override
750 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500751 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700752 newUserId, 0, reply));
753 }
754 @Override
755 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500756 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
Adrian Roosbe47b072014-09-03 00:08:56 +0200757 newUserId, 0));
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700758 }
Kenny Guy42979622015-04-13 18:03:05 +0000759 @Override
760 public void onForegroundProfileSwitch(int newProfileId) {
761 // Ignore.
762 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700763 });
764 } catch (RemoteException e) {
765 // TODO Auto-generated catch block
766 e.printStackTrace();
767 }
Adrian Roos46842d92014-03-27 14:58:03 +0100768
Jorim Jaggi237b0612015-05-01 14:28:49 -0700769 mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
770 mTrustManager.registerTrustListener(this);
Jim Millerf41fc962014-06-18 16:33:51 -0700771
Jim Miller9f0753f2015-03-23 23:59:22 -0700772 mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
Jorim Jaggiea657062015-04-28 13:45:11 -0700773 updateFingerprintListeningState();
774 }
775
776 private void updateFingerprintListeningState() {
777 boolean shouldListenForFingerprint = shouldListenForFingerprint();
778 if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
779 stopListeningForFingerprint();
780 } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
781 startListeningForFingerprint();
782 }
783 }
784
785 private boolean shouldListenForFingerprint() {
Jorim Jaggi237b0612015-05-01 14:28:49 -0700786 return mScreenOn && mKeyguardIsVisible && !mSwitchingUser
787 && mTrustManager.hasUserAuthenticatedSinceBoot(ActivityManager.getCurrentUser());
Jim Miller9f0753f2015-03-23 23:59:22 -0700788 }
789
Jim Millerce7eb6d2015-04-03 19:29:13 -0700790 private void startListeningForFingerprint() {
791 if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700792 int userId = ActivityManager.getCurrentUser();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700793 if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700794 && mFpm.getEnrolledFingerprints(userId).size() > 0) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700795 if (mFingerprintCancelSignal != null) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700796 mFingerprintCancelSignal.cancel();
797 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700798 mFingerprintCancelSignal = new CancellationSignal();
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700799 mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700800 setFingerprintRunningDetectionRunning(true);
Jim Miller9f0753f2015-03-23 23:59:22 -0700801 }
802 }
803
Jorim Jaggiea657062015-04-28 13:45:11 -0700804 private void stopListeningForFingerprint() {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700805 if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
806 if (isFingerprintDetectionRunning()) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700807 mFingerprintCancelSignal.cancel();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700808 mFingerprintCancelSignal = null;
Jim Miller9f0753f2015-03-23 23:59:22 -0700809 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700810 setFingerprintRunningDetectionRunning(false);
Jim Millerbbf1a742012-07-17 18:30:30 -0700811 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800812
Michael Jurkafff56142012-11-28 16:51:00 -0800813 private boolean isDeviceProvisionedInSettingsDb() {
814 return Settings.Global.getInt(mContext.getContentResolver(),
815 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
816 }
817
Jim Millerbbf1a742012-07-17 18:30:30 -0700818 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800819 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700820 @Override
821 public void onChange(boolean selfChange) {
822 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800823 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700824 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700825 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800826 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700827 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800828 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700829 };
830
831 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700832 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800833 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700834
835 // prevent a race condition between where we check the flag and where we register the
836 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800837 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700838 if (provisioned != mDeviceProvisioned) {
839 mDeviceProvisioned = provisioned;
840 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700841 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700842 }
843 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800844 }
845
Jim Millerbbf1a742012-07-17 18:30:30 -0700846 /**
847 * Handle {@link #MSG_DPM_STATE_CHANGED}
848 */
Jim Millerb0304762012-03-13 20:01:25 -0700849 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700850 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
851 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
852 if (cb != null) {
853 cb.onDevicePolicyManagerStateChanged();
854 }
Jim Millerb0304762012-03-13 20:01:25 -0700855 }
856 }
857
Jim Millerbbf1a742012-07-17 18:30:30 -0700858 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500859 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700860 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500861 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -0700862 mSwitchingUser = true;
863 updateFingerprintListeningState();
864
Jim Millerbbf1a742012-07-17 18:30:30 -0700865 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700866 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
867 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500868 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700869 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700870 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700871 try {
872 reply.sendResult(null);
873 } catch (RemoteException e) {
874 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700875 }
876
Jim Millerbbf1a742012-07-17 18:30:30 -0700877 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500878 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
879 */
880 protected void handleUserSwitchComplete(int userId) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -0700881 mSwitchingUser = false;
882 updateFingerprintListeningState();
883
Chris Wrenf41c61b2012-11-29 15:19:54 -0500884 for (int i = 0; i < mCallbacks.size(); i++) {
885 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
886 if (cb != null) {
887 cb.onUserSwitchComplete(userId);
888 }
889 }
890 }
891
892 /**
Jim Miller90873d52013-09-26 18:11:38 -0700893 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
894 * keyguard crashes sometime after boot, then it will never receive this
895 * broadcast and hence not handle the event. This method is ultimately called by
896 * PhoneWindowManager in this case.
897 */
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100898 public void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700899 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -0700900 }
901
902 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800903 * Handle {@link #MSG_BOOT_COMPLETED}
904 */
905 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700906 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800907 mBootCompleted = true;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800908 for (int i = 0; i < mCallbacks.size(); i++) {
909 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
910 if (cb != null) {
911 cb.onBootCompleted();
912 }
913 }
914 }
915
916 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800917 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800918 * destroyed.
919 */
920 public boolean hasBootCompleted() {
921 return mBootCompleted;
922 }
923
924 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700925 * Handle {@link #MSG_DEVICE_PROVISIONED}
926 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700927 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700928 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700929 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
930 if (cb != null) {
931 cb.onDeviceProvisioned();
932 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700933 }
Michael Jurkafff56142012-11-28 16:51:00 -0800934 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700935 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800936 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
937 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700938 }
939 }
940
Jim Millerbbf1a742012-07-17 18:30:30 -0700941 /**
942 * Handle {@link #MSG_PHONE_STATE_CHANGED}
943 */
Jim Millerc23024d2010-02-24 15:37:00 -0800944 protected void handlePhoneStateChanged(String newState) {
945 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700946 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
947 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
948 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
949 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
950 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
951 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
952 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700953 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700954 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
955 if (cb != null) {
956 cb.onPhoneStateChanged(mPhoneState);
957 }
Jim Millerc23024d2010-02-24 15:37:00 -0800958 }
959 }
960
Jim Millerbbf1a742012-07-17 18:30:30 -0700961 /**
962 * Handle {@link #MSG_RINGER_MODE_CHANGED}
963 */
Jim Miller47088bb2009-11-24 00:40:16 -0800964 protected void handleRingerModeChange(int mode) {
965 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700966 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700967 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700968 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
969 if (cb != null) {
970 cb.onRingerModeChanged(mode);
971 }
Jim Miller47088bb2009-11-24 00:40:16 -0800972 }
973 }
974
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800975 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800976 * Handle {@link #MSG_TIME_UPDATE}
977 */
978 private void handleTimeUpdate() {
979 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700980 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700981 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
982 if (cb != null) {
983 cb.onTimeChanged();
984 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800985 }
986 }
987
988 /**
989 * Handle {@link #MSG_BATTERY_UPDATE}
990 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700991 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800992 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700993 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
994 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700995 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700996 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700997 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
998 if (cb != null) {
999 cb.onRefreshBatteryInfo(status);
1000 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001001 }
1002 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001003 }
1004
1005 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001006 * Handle {@link #MSG_SIM_STATE_CHANGE}
1007 */
Jim Miller52a61332014-11-12 19:29:51 -08001008 private void handleSimStateChange(int subId, int slotId, State state) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001009
Jim Miller52a61332014-11-12 19:29:51 -08001010 if (DEBUG_SIM_STATES) {
1011 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
1012 + slotId + ", state=" + state +")");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001013 }
1014
Wink Savillea54bf652014-12-11 13:37:50 -08001015 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Jim Miller52a61332014-11-12 19:29:51 -08001016 Log.w(TAG, "invalid subId in handleSimStateChange()");
1017 return;
1018 }
1019
1020 SimData data = mSimDatas.get(subId);
1021 final boolean changed;
1022 if (data == null) {
1023 data = new SimData(state, slotId, subId);
1024 mSimDatas.put(subId, data);
1025 changed = true; // no data yet; force update
1026 } else {
1027 changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
1028 data.simState = state;
1029 data.subId = subId;
1030 data.slotId = slotId;
1031 }
1032 if (changed && state != State.UNKNOWN) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001033 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -07001034 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1035 if (cb != null) {
Jim Miller52a61332014-11-12 19:29:51 -08001036 cb.onSimStateChanged(subId, slotId, state);
Jim Millerdcb3d842012-08-23 19:18:12 -07001037 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001038 }
1039 }
1040 }
1041
Jim Millerbbf1a742012-07-17 18:30:30 -07001042 /**
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001043 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
1044 */
1045 private void handleKeyguardVisibilityChanged(int showing) {
1046 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -04001047 boolean isShowing = (showing == 1);
1048 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001049 for (int i = 0; i < mCallbacks.size(); i++) {
1050 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1051 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -04001052 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001053 }
1054 }
Jorim Jaggiea657062015-04-28 13:45:11 -07001055 updateFingerprintListeningState();
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001056 }
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
Jim Miller16464b82011-10-20 21:10:13 -07001086 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001087 final boolean nowPluggedIn = current.isPluggedIn();
1088 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -08001089 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -07001090 wasPluggedIn == true && nowPluggedIn == true
1091 && (old.status != current.status);
1092
1093 // change in plug state is always interesting
1094 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001095 return true;
1096 }
1097
1098 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -07001099 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001100 return true;
1101 }
1102
Jim Miller16464b82011-10-20 21:10:13 -07001103 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -07001104 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -07001105 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001106 }
1107 return false;
1108 }
1109
1110 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001111 * Remove the given observer's callback.
1112 *
Jim Miller6212cc02012-09-05 17:35:31 -07001113 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001114 */
Jim Miller6212cc02012-09-05 17:35:31 -07001115 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1116 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1117 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1118 if (mCallbacks.get(i).get() == callback) {
1119 mCallbacks.remove(i);
1120 }
1121 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001122 }
1123
1124 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001125 * Register to receive notifications about general keyguard information
1126 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -07001127 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001128 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001129 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -07001130 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1131 // Prevent adding duplicate callbacks
1132 for (int i = 0; i < mCallbacks.size(); i++) {
1133 if (mCallbacks.get(i).get() == callback) {
1134 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1135 new Exception("Called by"));
1136 return;
Jim Millerdcb3d842012-08-23 19:18:12 -07001137 }
1138 }
Jim Miller6212cc02012-09-05 17:35:31 -07001139 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1140 removeCallback(null); // remove unused references
1141 sendUpdates(callback);
1142 }
1143
1144 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1145 // Notify listener of the current state
1146 callback.onRefreshBatteryInfo(mBatteryStatus);
1147 callback.onTimeChanged();
1148 callback.onRingerModeChanged(mRingMode);
1149 callback.onPhoneStateChanged(mPhoneState);
Jason Monk9ff69bd2014-12-02 16:43:17 -05001150 callback.onRefreshCarrierInfo();
Jim Miller6212cc02012-09-05 17:35:31 -07001151 callback.onClockVisibilityChanged();
Jim Miller52a61332014-11-12 19:29:51 -08001152 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
1153 final SimData state = data.getValue();
1154 callback.onSimStateChanged(state.subId, state.slotId, state.simState);
1155 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001156 }
1157
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001158 public void sendKeyguardVisibilityChanged(boolean showing) {
1159 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1160 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1161 message.arg1 = showing ? 1 : 0;
1162 message.sendToTarget();
1163 }
1164
Adrian Roosb6011622014-05-14 15:52:53 +02001165 /**
1166 * @see #handleKeyguardBouncerChanged(int)
1167 */
1168 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1169 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1170 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1171 message.arg1 = showingBouncer ? 1 : 0;
1172 message.sendToTarget();
1173 }
1174
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001175 /**
Jim Miller90d5d462011-11-17 16:57:01 -08001176 * 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 -08001177 * have the information earlier than waiting for the intent
1178 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -08001179 *
1180 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1181 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001182 */
Jim Miller52a61332014-11-12 19:29:51 -08001183 public void reportSimUnlocked(int subId) {
1184 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
1185 int slotId = SubscriptionManager.getSlotId(subId);
1186 handleSimStateChange(subId, slotId, State.READY);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001187 }
1188
Brian Colonna7fce3802013-09-17 15:51:32 -04001189 /**
1190 * Report that the emergency call button has been pressed and the emergency dialer is
1191 * about to be displayed.
1192 *
1193 * @param bypassHandler runs immediately.
1194 *
1195 * NOTE: Must be called from UI thread if bypassHandler == true.
1196 */
1197 public void reportEmergencyCallAction(boolean bypassHandler) {
1198 if (!bypassHandler) {
1199 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1200 } else {
1201 handleReportEmergencyCallAction();
1202 }
1203 }
1204
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001205 /**
1206 * @return Whether the device is provisioned (whether they have gone through
1207 * the setup wizard)
1208 */
1209 public boolean isDeviceProvisioned() {
1210 return mDeviceProvisioned;
1211 }
1212
Jorim Jaggi9f743032015-05-04 15:22:40 -07001213 public void clearFailedUnlockAttempts() {
1214 mFailedAttempts.delete(sCurrentUser);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001215 }
1216
Jorim Jaggi9f743032015-05-04 15:22:40 -07001217 public int getFailedUnlockAttempts() {
1218 return mFailedAttempts.get(sCurrentUser, 0);
1219 }
1220
1221 public void reportFailedUnlockAttempt() {
1222 mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001223 }
1224
Jim Millerf41fc962014-06-18 16:33:51 -07001225 public void clearFingerprintRecognized() {
Jim Miller9f0753f2015-03-23 23:59:22 -07001226 mUserFingerprintAuthenticated.clear();
Jim Millerf41fc962014-06-18 16:33:51 -07001227 }
1228
Jim Miller52a61332014-11-12 19:29:51 -08001229 public boolean isSimPinVoiceSecure() {
1230 // TODO: only count SIMs that handle voice
1231 return isSimPinSecure();
Jim Millerdcb3d842012-08-23 19:18:12 -07001232 }
1233
1234 public boolean isSimPinSecure() {
Jim Miller52a61332014-11-12 19:29:51 -08001235 // True if any SIM is pin secure
1236 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
1237 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
1238 }
1239 return false;
1240 }
1241
Jason Monk9ff69bd2014-12-02 16:43:17 -05001242 public State getSimState(int subId) {
Jim Miller52a61332014-11-12 19:29:51 -08001243 if (mSimDatas.containsKey(subId)) {
1244 return mSimDatas.get(subId).simState;
1245 } else {
1246 return State.UNKNOWN;
1247 }
1248 }
1249
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001250 /**
1251 * @return true if and only if the state has changed for the specified {@code slotId}
1252 */
1253 private boolean refreshSimState(int subId, int slotId) {
Jim Miller52a61332014-11-12 19:29:51 -08001254
1255 // This is awful. It exists because there are two APIs for getting the SIM status
1256 // that don't return the complete set of values and have different types. In Keyguard we
1257 // need IccCardConstants, but TelephonyManager would only give us
1258 // TelephonyManager.SIM_STATE*, so we retrieve it manually.
xinhe18b9c3c2014-12-02 15:03:20 -08001259 final TelephonyManager tele = TelephonyManager.from(mContext);
1260 int simState = tele.getSimState(slotId);
Jim Miller52a61332014-11-12 19:29:51 -08001261 State state;
1262 try {
xinhe18b9c3c2014-12-02 15:03:20 -08001263 state = State.intToState(simState);
Jim Miller52a61332014-11-12 19:29:51 -08001264 } catch(IllegalArgumentException ex) {
xinhe18b9c3c2014-12-02 15:03:20 -08001265 Log.w(TAG, "Unknown sim state: " + simState);
Jim Miller52a61332014-11-12 19:29:51 -08001266 state = State.UNKNOWN;
John Spurlock5b13e922015-01-07 11:04:58 -05001267 }
Jorim Jaggi01ba98b2015-01-13 21:33:45 +01001268 SimData data = mSimDatas.get(subId);
1269 final boolean changed;
1270 if (data == null) {
1271 data = new SimData(state, slotId, subId);
1272 mSimDatas.put(subId, data);
1273 changed = true; // no data yet; force update
1274 } else {
1275 changed = data.simState != state;
1276 data.simState = state;
1277 }
1278 return changed;
Jim Millerdcb3d842012-08-23 19:18:12 -07001279 }
1280
1281 public static boolean isSimPinSecure(IccCardConstants.State state) {
1282 final IccCardConstants.State simState = state;
1283 return (simState == IccCardConstants.State.PIN_REQUIRED
1284 || simState == IccCardConstants.State.PUK_REQUIRED
1285 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001286 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001287
1288 public DisplayClientState getCachedDisplayClientState() {
1289 return mDisplayClientState;
1290 }
Jim Miller20daffd2013-10-07 14:59:53 -07001291
1292 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1293 // (KeyguardViewMediator, KeyguardHostView)
1294 public void dispatchScreenTurnedOn() {
1295 synchronized (this) {
1296 mScreenOn = true;
1297 }
1298 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1299 }
1300
John Spurlock36a13422015-03-24 21:15:48 -04001301 public void dispatchScreenTurnedOff(int why) {
Jim Miller20daffd2013-10-07 14:59:53 -07001302 synchronized(this) {
1303 mScreenOn = false;
1304 }
1305 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1306 }
1307
1308 public boolean isScreenOn() {
1309 return mScreenOn;
1310 }
Jim Miller52a61332014-11-12 19:29:51 -08001311
1312 /**
1313 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
1314 * @param state
Wink Savilled09c4ca2014-11-22 10:08:16 -08001315 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
Jim Miller52a61332014-11-12 19:29:51 -08001316 */
1317 public int getNextSubIdForState(State state) {
1318 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
Wink Savilled09c4ca2014-11-22 10:08:16 -08001319 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Jim Miller52a61332014-11-12 19:29:51 -08001320 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
1321 for (int i = 0; i < list.size(); i++) {
1322 final SubscriptionInfo info = list.get(i);
1323 final int id = info.getSubscriptionId();
1324 int slotId = SubscriptionManager.getSlotId(id);
1325 if (state == getSimState(id) && bestSlotId > slotId ) {
1326 resultId = id;
1327 bestSlotId = slotId;
1328 }
1329 }
1330 return resultId;
1331 }
1332
1333 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) {
1334 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
1335 for (int i = 0; i < list.size(); i++) {
1336 SubscriptionInfo info = list.get(i);
1337 if (subId == info.getSubscriptionId()) return info;
1338 }
1339 return null; // not found
1340 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001341}