blob: 84bacc33404bd2077106c119fe6ae8bd7e1b6d73 [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
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070019import android.app.ActivityManagerNative;
Jorim Jaggic7dea6e2014-07-26 14:36:57 +020020import android.app.AlarmManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070021import android.app.IUserSwitchObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070022import android.app.PendingIntent;
Jim Millerb0304762012-03-13 20:01:25 -070023import android.app.admin.DevicePolicyManager;
Adrian Roos46842d92014-03-27 14:58:03 +010024import android.app.trust.TrustManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080025import android.content.BroadcastReceiver;
Jim Millerf41fc962014-06-18 16:33:51 -070026import android.content.ContentResolver;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080027import 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;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080043import android.os.Handler;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070044import android.os.IRemoteCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080045import android.os.Message;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070046import android.os.RemoteException;
Amith Yamasanie8e93a12013-05-09 18:12:30 -070047import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080048import android.provider.Settings;
Dianne Hackbornb7e787f2009-05-07 15:55:42 -070049
Wink Savillea639b312012-07-10 12:37:54 -070050import com.android.internal.telephony.IccCardConstants;
Jim Miller52a61332014-11-12 19:29:51 -080051import com.android.internal.telephony.IccCardConstants.State;
52import com.android.internal.telephony.PhoneConstants;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080053import com.android.internal.telephony.TelephonyIntents;
Jim Miller52a61332014-11-12 19:29:51 -080054import com.android.internal.telephony.TelephonyProperties;
Jim Millerc23024d2010-02-24 15:37:00 -080055
Jim Millerf41fc962014-06-18 16:33:51 -070056import android.service.fingerprint.FingerprintManager;
57import android.service.fingerprint.FingerprintManagerReceiver;
58import android.service.fingerprint.FingerprintUtils;
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;
65
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080066import com.google.android.collect.Lists;
67
Jim Millerdcb3d842012-08-23 19:18:12 -070068import java.lang.ref.WeakReference;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080069import java.util.ArrayList;
Jim Miller52a61332014-11-12 19:29:51 -080070import java.util.HashMap;
71import java.util.List;
72import java.util.Map.Entry;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080073
74/**
75 * Watches for updates that may be interesting to the keyguard, and provides
76 * the up to date information as well as a registration for callbacks that care
77 * to be updated.
78 *
79 * Note: under time crunch, this has been extended to include some stuff that
80 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
Jim Miller258341c2012-08-30 16:50:10 -070081 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
82 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080083 */
Adrian Roos46842d92014-03-27 14:58:03 +010084public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080085
Jim Millerbbf1a742012-07-17 18:30:30 -070086 private static final String TAG = "KeyguardUpdateMonitor";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010087 private static final boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller52a61332014-11-12 19:29:51 -080088 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
Uriel Rodriguezaa249062012-06-13 17:30:13 -040089 private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
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;
Jeff Sharkey054340d2011-09-01 22:28:03 -0700103 private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700104 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -0700105 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500106 private static final int MSG_USER_SWITCHING = 310;
Jim Miller57375342012-09-09 15:20:31 -0700107 private static final int MSG_USER_REMOVED = 311;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400108 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
Jim Millerf41fc962014-06-18 16:33:51 -0700109 private static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500110 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Millerf41fc962014-06-18 16:33:51 -0700111 private static final int MSG_SET_CURRENT_CLIENT_ID = 315;
112 private static final int MSG_SET_PLAYBACK_STATE = 316;
113 private static final int MSG_USER_INFO_CHANGED = 317;
114 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jim Miller20daffd2013-10-07 14:59:53 -0700115 private static final int MSG_SCREEN_TURNED_ON = 319;
116 private static final int MSG_SCREEN_TURNED_OFF = 320;
Adrian Roosb6011622014-05-14 15:52:53 +0200117 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
Jim Millerf41fc962014-06-18 16:33:51 -0700118 private static final int MSG_FINGERPRINT_PROCESSED = 323;
119 private static final int MSG_FINGERPRINT_ACQUIRED = 324;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200120 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 325;
Jim Miller52a61332014-11-12 19:29:51 -0800121 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 326;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800122
Jim Millerdcb3d842012-08-23 19:18:12 -0700123 private static KeyguardUpdateMonitor sInstance;
124
Jim Millerbbf1a742012-07-17 18:30:30 -0700125 private final Context mContext;
Jim Miller52a61332014-11-12 19:29:51 -0800126 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
Jim Millerbbf1a742012-07-17 18:30:30 -0700127
Jim Millerbbf1a742012-07-17 18:30:30 -0700128 private int mRingMode;
129 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400130 private boolean mKeyguardIsVisible;
Adrian Roosb6011622014-05-14 15:52:53 +0200131 private boolean mBouncer;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800132 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700133
Jim Millerdcb3d842012-08-23 19:18:12 -0700134 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700135 private boolean mDeviceProvisioned;
136
Jim Millerdcb3d842012-08-23 19:18:12 -0700137 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700138 private BatteryStatus mBatteryStatus;
139
Jim Millerdcb3d842012-08-23 19:18:12 -0700140 // Password attempts
Jim Millerbbf1a742012-07-17 18:30:30 -0700141 private int mFailedAttempts = 0;
142 private int mFailedBiometricUnlockAttempts = 0;
143
Jim Miller0ff7f012012-10-11 20:40:01 -0700144 private boolean mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400145
Jim Millerbbf1a742012-07-17 18:30:30 -0700146 private boolean mClockVisible;
147
Jim Miller6212cc02012-09-05 17:35:31 -0700148 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700149 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800150 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700151
Brian Colonnaa5239892013-04-15 11:45:40 -0400152 private boolean mSwitchingUser;
153
Jim Miller20daffd2013-10-07 14:59:53 -0700154 private boolean mScreenOn;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800155 private SubscriptionManager mSubscriptionManager;
156 private List<SubscriptionInfo> mSubscriptionInfo;
Jim Miller20daffd2013-10-07 14:59:53 -0700157
Jim Millerbbf1a742012-07-17 18:30:30 -0700158 private final Handler mHandler = new Handler() {
159 @Override
160 public void handleMessage(Message msg) {
161 switch (msg.what) {
162 case MSG_TIME_UPDATE:
163 handleTimeUpdate();
164 break;
165 case MSG_BATTERY_UPDATE:
166 handleBatteryUpdate((BatteryStatus) msg.obj);
167 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700168 case MSG_SIM_STATE_CHANGE:
Jim Miller52a61332014-11-12 19:29:51 -0800169 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700170 break;
171 case MSG_RINGER_MODE_CHANGED:
172 handleRingerModeChange(msg.arg1);
173 break;
174 case MSG_PHONE_STATE_CHANGED:
Adrian Roosb6011622014-05-14 15:52:53 +0200175 handlePhoneStateChanged((String) msg.obj);
Jim Millerbbf1a742012-07-17 18:30:30 -0700176 break;
177 case MSG_CLOCK_VISIBILITY_CHANGED:
178 handleClockVisibilityChanged();
179 break;
180 case MSG_DEVICE_PROVISIONED:
181 handleDeviceProvisioned();
182 break;
183 case MSG_DPM_STATE_CHANGED:
184 handleDevicePolicyManagerStateChanged();
185 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500186 case MSG_USER_SWITCHING:
Adrian Roosb6011622014-05-14 15:52:53 +0200187 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
Chris Wrenf41c61b2012-11-29 15:19:54 -0500188 break;
189 case MSG_USER_SWITCH_COMPLETE:
190 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700191 break;
192 case MSG_USER_REMOVED:
193 handleUserRemoved(msg.arg1);
194 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400195 case MSG_KEYGUARD_VISIBILITY_CHANGED:
196 handleKeyguardVisibilityChanged(msg.arg1);
197 break;
Adrian Roosb6011622014-05-14 15:52:53 +0200198 case MSG_KEYGUARD_BOUNCER_CHANGED:
199 handleKeyguardBouncerChanged(msg.arg1);
200 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800201 case MSG_BOOT_COMPLETED:
202 handleBootCompleted();
203 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700204 case MSG_USER_INFO_CHANGED:
205 handleUserInfoChanged(msg.arg1);
206 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400207 case MSG_REPORT_EMERGENCY_CALL_ACTION:
208 handleReportEmergencyCallAction();
209 break;
Jim Miller20daffd2013-10-07 14:59:53 -0700210 case MSG_SCREEN_TURNED_OFF:
211 handleScreenTurnedOff(msg.arg1);
212 break;
213 case MSG_SCREEN_TURNED_ON:
214 handleScreenTurnedOn();
215 break;
Jim Millerf41fc962014-06-18 16:33:51 -0700216 case MSG_FINGERPRINT_ACQUIRED:
217 handleFingerprintAcquired(msg.arg1);
218 break;
219 case MSG_FINGERPRINT_PROCESSED:
220 handleFingerprintProcessed(msg.arg1);
221 break;
Jorim Jaggie7b12522014-08-06 16:41:21 +0200222 case MSG_FACE_UNLOCK_STATE_CHANGED:
Adrian Roos4a410172014-08-20 17:41:44 +0200223 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200224 break;
Jim Miller52a61332014-11-12 19:29:51 -0800225 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED:
226 handleSimSubscriptionInfoChanged();
227 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700228 }
229 }
230 };
231
Wink Savilled09c4ca2014-11-22 10:08:16 -0800232 private OnSubscriptionsChangedListener mSubscriptionListener =
233 new OnSubscriptionsChangedListener() {
Jim Miller52a61332014-11-12 19:29:51 -0800234 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800235 public void onSubscriptionsChanged() {
Jim Miller52a61332014-11-12 19:29:51 -0800236 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
237 }
238 };
239
Adrian Roos46842d92014-03-27 14:58:03 +0100240 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
Adrian Roos7861c662014-07-25 15:37:28 +0200241 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
Jim Millerf41fc962014-06-18 16:33:51 -0700242 private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
Adrian Roos4a410172014-08-20 17:41:44 +0200243 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
Adrian Roos46842d92014-03-27 14:58:03 +0100244
245 @Override
Adrian Roos3c9a3502014-08-06 19:09:45 +0200246 public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
Adrian Roos46842d92014-03-27 14:58:03 +0100247 mUserHasTrust.put(userId, enabled);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200248
249 for (int i = 0; i < mCallbacks.size(); i++) {
250 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
251 if (cb != null) {
252 cb.onTrustChanged(userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200253 if (enabled && initiatedByUser) {
254 cb.onTrustInitiatedByUser(userId);
255 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200256 }
257 }
Adrian Roos46842d92014-03-27 14:58:03 +0100258 }
259
Jim Miller52a61332014-11-12 19:29:51 -0800260 protected void handleSimSubscriptionInfoChanged() {
261 if (DEBUG_SIM_STATES) {
262 Log.v(TAG, "onSubscriptionInfoChanged()");
Wink Savilled09c4ca2014-11-22 10:08:16 -0800263 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
264 if (sil != null) {
265 for (SubscriptionInfo subInfo : sil) {
266 Log.v(TAG, "SubInfo:" + subInfo);
267 }
268 } else {
269 Log.v(TAG, "onSubscriptionInfoChanged: list is null");
Jim Miller52a61332014-11-12 19:29:51 -0800270 }
271 }
272 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
273
274 // Hack level over 9000: Because the subscription id is not yet valid when we see the
275 // first update in handleSimStateChange, we need to force refresh all all SIM states
276 // so the subscription id for them is consistent.
277 for (int i = 0; i < subscriptionInfos.size(); i++) {
278 SubscriptionInfo info = subscriptionInfos.get(i);
279 refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
280 }
281 for (int i = 0; i < subscriptionInfos.size(); i++) {
282 SimData data = mSimDatas.get(mSubscriptionInfo.get(i).getSubscriptionId());
283 for (int j = 0; j < mCallbacks.size(); j++) {
284 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
285 if (cb != null) {
286 cb.onSimStateChanged(data.subId, data.slotId, data.simState);
287 }
288 }
289 }
Jason Monk6c985dc2015-01-09 16:07:14 -0500290 for (int j = 0; j < mCallbacks.size(); j++) {
291 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
292 if (cb != null) {
293 cb.onRefreshCarrierInfo();
294 }
295 }
Jim Miller52a61332014-11-12 19:29:51 -0800296 }
297
Wink Savilled09c4ca2014-11-22 10:08:16 -0800298 /** @return List of SubscriptionInfo records, maybe empty but never null */
Jim Miller52a61332014-11-12 19:29:51 -0800299 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
Wink Savilled09c4ca2014-11-22 10:08:16 -0800300 List<SubscriptionInfo> sil = mSubscriptionInfo;
301 if (sil == null || forceReload) {
302 sil = mSubscriptionManager.getActiveSubscriptionInfoList();
303 }
304 if (sil == null) {
305 // getActiveSubscriptionInfoList was null callers expect an empty list.
306 mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
307 } else {
308 mSubscriptionInfo = sil;
Jim Miller52a61332014-11-12 19:29:51 -0800309 }
310 return mSubscriptionInfo;
311 }
312
Adrian Roos7861c662014-07-25 15:37:28 +0200313 @Override
314 public void onTrustManagedChanged(boolean managed, int userId) {
315 mUserTrustIsManaged.put(userId, managed);
316
317 for (int i = 0; i < mCallbacks.size(); i++) {
318 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
319 if (cb != null) {
320 cb.onTrustManagedChanged(userId);
321 }
322 }
323 }
324
Jim Millerf41fc962014-06-18 16:33:51 -0700325 private void onFingerprintRecognized(int userId) {
326 mUserFingerprintRecognized.put(userId, true);
327 for (int i = 0; i < mCallbacks.size(); i++) {
328 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
329 if (cb != null) {
330 cb.onFingerprintRecognized(userId);
331 }
332 }
333 }
334
335 private void handleFingerprintProcessed(int fingerprintId) {
336 if (fingerprintId == 0) return; // not a valid fingerprint
337
338 final int userId;
339 try {
340 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
341 } catch (RemoteException e) {
342 Log.e(TAG, "Failed to get current user id: ", e);
343 return;
344 }
Jim Miller06e34502014-07-17 14:46:05 -0700345 if (isFingerprintDisabled(userId)) {
346 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
347 return;
348 }
Jim Millerf41fc962014-06-18 16:33:51 -0700349 final ContentResolver res = mContext.getContentResolver();
350 final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
351 for (int i = 0; i < ids.length; i++) {
352 if (ids[i] == fingerprintId) {
353 onFingerprintRecognized(userId);
354 }
355 }
356 }
357
358 private void handleFingerprintAcquired(int info) {
359 for (int i = 0; i < mCallbacks.size(); i++) {
360 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
361 if (cb != null) {
362 cb.onFingerprintAcquired(info);
363 }
364 }
365 }
366
Adrian Roos4a410172014-08-20 17:41:44 +0200367 private void handleFaceUnlockStateChanged(boolean running, int userId) {
368 mUserFaceUnlockRunning.put(userId, running);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200369 for (int i = 0; i < mCallbacks.size(); i++) {
370 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
371 if (cb != null) {
Adrian Roos4a410172014-08-20 17:41:44 +0200372 cb.onFaceUnlockStateChanged(running, userId);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200373 }
374 }
375 }
376
Adrian Roos4a410172014-08-20 17:41:44 +0200377 public boolean isFaceUnlockRunning(int userId) {
378 return mUserFaceUnlockRunning.get(userId);
379 }
380
Jim Miller50e62182014-04-23 17:25:00 -0700381 private boolean isTrustDisabled(int userId) {
382 final DevicePolicyManager dpm =
383 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
384 if (dpm != null) {
385 // TODO once UI is finalized
386 final boolean disabledByGlobalActions = false;
387 final boolean disabledBySettings = false;
388
389 // Don't allow trust agent if device is secured with a SIM PIN. This is here
390 // mainly because there's no other way to prompt the user to enter their SIM PIN
391 // once they get past the keyguard screen.
392 final boolean disabledBySimPin = isSimPinSecure();
393
394 final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId)
395 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
396 return disabledByDpm || disabledByGlobalActions || disabledBySettings
397 || disabledBySimPin;
398 }
399 return false;
400 }
401
Jim Miller06e34502014-07-17 14:46:05 -0700402 private boolean isFingerprintDisabled(int userId) {
403 final DevicePolicyManager dpm =
404 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
405 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
406 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
407 }
408
Adrian Roos46842d92014-03-27 14:58:03 +0100409 public boolean getUserHasTrust(int userId) {
Jim Millerf41fc962014-06-18 16:33:51 -0700410 return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
411 || mUserFingerprintRecognized.get(userId);
Adrian Roos46842d92014-03-27 14:58:03 +0100412 }
413
Adrian Roos7861c662014-07-25 15:37:28 +0200414 public boolean getUserTrustIsManaged(int userId) {
415 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
416 }
417
Jim Miller8f09fd22013-03-14 19:04:28 -0700418 static class DisplayClientState {
419 public int clientGeneration;
420 public boolean clearing;
421 public PendingIntent intent;
422 public int playbackState;
423 public long playbackEventTime;
424 }
425
426 private DisplayClientState mDisplayClientState = new DisplayClientState();
427
Jim Millerbbf1a742012-07-17 18:30:30 -0700428 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
429
430 public void onReceive(Context context, Intent intent) {
431 final String action = intent.getAction();
432 if (DEBUG) Log.d(TAG, "received broadcast " + action);
433
434 if (Intent.ACTION_TIME_TICK.equals(action)
435 || Intent.ACTION_TIME_CHANGED.equals(action)
Adrian Roos48c796c2014-09-01 14:59:23 +0200436 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700437 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700438 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
439 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
440 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
441 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
442 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
443 final Message msg = mHandler.obtainMessage(
444 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
445 mHandler.sendMessage(msg);
446 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller52a61332014-11-12 19:29:51 -0800447 SimData args = SimData.fromIntent(intent);
Jim Millerbbf1a742012-07-17 18:30:30 -0700448 if (DEBUG_SIM_STATES) {
Jim Miller52a61332014-11-12 19:29:51 -0800449 Log.v(TAG, "action " + action
450 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
451 + " slotId: " + args.slotId + " subid: " + args.subId);
Jim Millerbbf1a742012-07-17 18:30:30 -0700452 }
Jim Miller52a61332014-11-12 19:29:51 -0800453 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
454 .sendToTarget();
Jim Millerbbf1a742012-07-17 18:30:30 -0700455 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
456 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
457 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
458 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
459 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
460 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
Jim Millerbbf1a742012-07-17 18:30:30 -0700461 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
462 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
Jim Millerdcb3d842012-08-23 19:18:12 -0700463 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800464 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700465 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700466 }
467 }
468 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700469
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700470 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
471
472 public void onReceive(Context context, Intent intent) {
473 final String action = intent.getAction();
Adrian Roos48c796c2014-09-01 14:59:23 +0200474 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
475 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
476 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700477 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
478 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
Adrian Roos48c796c2014-09-01 14:59:23 +0200479 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
480 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
481 getSendingUserId()));
482 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
483 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
484 getSendingUserId()));
485 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
486 .equals(action)) {
487 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700488 }
489 }
490 };
Jim Millerf41fc962014-06-18 16:33:51 -0700491 private FingerprintManagerReceiver mFingerprintManagerReceiver =
492 new FingerprintManagerReceiver() {
493 @Override
494 public void onProcessed(int fingerprintId) {
495 mHandler.obtainMessage(MSG_FINGERPRINT_PROCESSED, fingerprintId, 0).sendToTarget();
496 };
497
498 @Override
499 public void onAcquired(int info) {
500 mHandler.obtainMessage(MSG_FINGERPRINT_ACQUIRED, info, 0).sendToTarget();
501 }
502
503 @Override
504 public void onError(int error) {
505 if (DEBUG) Log.w(TAG, "FingerprintManager reported error: " + error);
506 }
507 };
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700508
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800509 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800510 * When we receive a
511 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700512 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800513 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800514 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800515 */
Jim Miller52a61332014-11-12 19:29:51 -0800516 private static class SimData {
517 public State simState;
518 public int slotId;
519 public int subId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800520
Jim Miller52a61332014-11-12 19:29:51 -0800521 SimData(State state, int slot, int id) {
Jim Miller90d5d462011-11-17 16:57:01 -0800522 simState = state;
Jim Miller52a61332014-11-12 19:29:51 -0800523 slotId = slot;
524 subId = id;
Jim Miller90d5d462011-11-17 16:57:01 -0800525 }
526
Jim Miller52a61332014-11-12 19:29:51 -0800527 static SimData fromIntent(Intent intent) {
528 State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800529 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
530 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
531 }
Wink Savillea639b312012-07-10 12:37:54 -0700532 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
Jim Miller52a61332014-11-12 19:29:51 -0800533 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
534 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
Wink Savilled09c4ca2014-11-22 10:08:16 -0800535 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea639b312012-07-10 12:37:54 -0700536 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700537 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700538 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700539
Wink Savillea639b312012-07-10 12:37:54 -0700540 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700541 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700542 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700543 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700544 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700545 }
Wink Savillea639b312012-07-10 12:37:54 -0700546 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
547 state = IccCardConstants.State.READY;
548 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800549 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700550 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
551 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
552 state = IccCardConstants.State.PIN_REQUIRED;
553 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
554 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800555 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700556 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800557 }
Wink Savillea639b312012-07-10 12:37:54 -0700558 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
559 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700560 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
561 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
562 // This is required because telephony doesn't return to "READY" after
563 // these state transitions. See bug 7197471.
564 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800565 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700566 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800567 }
Jim Miller52a61332014-11-12 19:29:51 -0800568 return new SimData(state, slotId, subId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800569 }
570
571 public String toString() {
Jim Miller52a61332014-11-12 19:29:51 -0800572 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800573 }
574 }
575
Adrian Roos12c1ef52014-06-04 13:54:08 +0200576 public static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700577 public final int status;
578 public final int level;
579 public final int plugged;
580 public final int health;
581 public BatteryStatus(int status, int level, int plugged, int health) {
582 this.status = status;
583 this.level = level;
584 this.plugged = plugged;
585 this.health = health;
586 }
587
Jim Millerbbf1a742012-07-17 18:30:30 -0700588 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700589 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700590 * @return true if the device is plugged in.
591 */
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100592 public boolean isPluggedIn() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700593 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700594 || plugged == BatteryManager.BATTERY_PLUGGED_USB
595 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700596 }
597
598 /**
599 * Whether or not the device is charged. Note that some devices never return 100% for
600 * battery level, so this allows either battery level or status to determine if the
601 * battery is charged.
602 * @return true if the device is charged
603 */
604 public boolean isCharged() {
605 return status == BATTERY_STATUS_FULL || level >= 100;
606 }
607
608 /**
609 * Whether battery is low and needs to be charged.
610 * @return true if battery is low
611 */
612 public boolean isBatteryLow() {
613 return level < LOW_BATTERY_THRESHOLD;
614 }
615
Jim Miller16464b82011-10-20 21:10:13 -0700616 }
617
Jim Millerdcb3d842012-08-23 19:18:12 -0700618 public static KeyguardUpdateMonitor getInstance(Context context) {
619 if (sInstance == null) {
620 sInstance = new KeyguardUpdateMonitor(context);
621 }
622 return sInstance;
623 }
624
Jim Miller20daffd2013-10-07 14:59:53 -0700625 protected void handleScreenTurnedOn() {
626 final int count = mCallbacks.size();
627 for (int i = 0; i < count; i++) {
628 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
629 if (cb != null) {
630 cb.onScreenTurnedOn();
631 }
632 }
633 }
634
635 protected void handleScreenTurnedOff(int arg1) {
Jim Millerf41fc962014-06-18 16:33:51 -0700636 clearFingerprintRecognized();
Jim Miller20daffd2013-10-07 14:59:53 -0700637 final int count = mCallbacks.size();
638 for (int i = 0; i < count; i++) {
639 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
640 if (cb != null) {
641 cb.onScreenTurnedOff(arg1);
642 }
643 }
644 }
645
Adam Powell43a372f2013-09-27 17:43:53 -0700646 /**
647 * IMPORTANT: Must be called from UI thread.
648 */
649 public void dispatchSetBackground(Bitmap bmp) {
650 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
651 final int count = mCallbacks.size();
652 for (int i = 0; i < count; i++) {
653 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
654 if (cb != null) {
655 cb.onSetBackground(bmp);
656 }
657 }
658 }
659
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700660 private void handleUserInfoChanged(int userId) {
661 for (int i = 0; i < mCallbacks.size(); i++) {
662 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
663 if (cb != null) {
664 cb.onUserInfoChanged(userId);
665 }
666 }
667 }
668
Jim Millerdcb3d842012-08-23 19:18:12 -0700669 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800670 mContext = context;
Wink Savilled09c4ca2014-11-22 10:08:16 -0800671 mSubscriptionManager = SubscriptionManager.from(context);
Michael Jurkafff56142012-11-28 16:51:00 -0800672 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800673 // Since device can't be un-provisioned, we only need to register a content observer
674 // to update mDeviceProvisioned when we are...
675 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700676 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800677 }
Jim Miller47088bb2009-11-24 00:40:16 -0800678
Jim Millerbbf1a742012-07-17 18:30:30 -0700679 // Take a guess at initial SIM state, battery status and PLMN until we get an update
Jim Miller16464b82011-10-20 21:10:13 -0700680 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800681
Jim Millerbbf1a742012-07-17 18:30:30 -0700682 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800683 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800684 filter.addAction(Intent.ACTION_TIME_TICK);
685 filter.addAction(Intent.ACTION_TIME_CHANGED);
686 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
687 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
688 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800689 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Jim Miller47088bb2009-11-24 00:40:16 -0800690 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700691 filter.addAction(Intent.ACTION_USER_REMOVED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700692 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700693
Adam Cohenc276e822012-11-08 13:01:08 -0800694 final IntentFilter bootCompleteFilter = new IntentFilter();
695 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
696 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
697 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
698
Adrian Roos48c796c2014-09-01 14:59:23 +0200699 final IntentFilter allUserFilter = new IntentFilter();
700 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
701 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
702 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
703 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
704 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
705 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700706 null, null);
707
Wink Savilled09c4ca2014-11-22 10:08:16 -0800708 mSubscriptionManager.registerOnSubscriptionsChangedListener(mSubscriptionListener);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700709 try {
710 ActivityManagerNative.getDefault().registerUserSwitchObserver(
711 new IUserSwitchObserver.Stub() {
712 @Override
713 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500714 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700715 newUserId, 0, reply));
Brian Colonnaa5239892013-04-15 11:45:40 -0400716 mSwitchingUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700717 }
718 @Override
719 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500720 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
Adrian Roosbe47b072014-09-03 00:08:56 +0200721 newUserId, 0));
Brian Colonnaa5239892013-04-15 11:45:40 -0400722 mSwitchingUser = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700723 }
724 });
725 } catch (RemoteException e) {
726 // TODO Auto-generated catch block
727 e.printStackTrace();
728 }
Adrian Roos46842d92014-03-27 14:58:03 +0100729
730 TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
731 trustManager.registerTrustListener(this);
Jim Millerf41fc962014-06-18 16:33:51 -0700732
733 FingerprintManager fpm;
734 fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
735 fpm.startListening(mFingerprintManagerReceiver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700736 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800737
Michael Jurkafff56142012-11-28 16:51:00 -0800738 private boolean isDeviceProvisionedInSettingsDb() {
739 return Settings.Global.getInt(mContext.getContentResolver(),
740 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
741 }
742
Jim Millerbbf1a742012-07-17 18:30:30 -0700743 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800744 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700745 @Override
746 public void onChange(boolean selfChange) {
747 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800748 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700749 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700750 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800751 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700752 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800753 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700754 };
755
756 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700757 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800758 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700759
760 // prevent a race condition between where we check the flag and where we register the
761 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800762 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700763 if (provisioned != mDeviceProvisioned) {
764 mDeviceProvisioned = provisioned;
765 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700766 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700767 }
768 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800769 }
770
Jim Millerbbf1a742012-07-17 18:30:30 -0700771 /**
772 * Handle {@link #MSG_DPM_STATE_CHANGED}
773 */
Jim Millerb0304762012-03-13 20:01:25 -0700774 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700775 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
776 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
777 if (cb != null) {
778 cb.onDevicePolicyManagerStateChanged();
779 }
Jim Millerb0304762012-03-13 20:01:25 -0700780 }
781 }
782
Jim Millerbbf1a742012-07-17 18:30:30 -0700783 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500784 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700785 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500786 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700787 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700788 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
789 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500790 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700791 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700792 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700793 try {
794 reply.sendResult(null);
795 } catch (RemoteException e) {
796 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700797 }
798
Jim Millerbbf1a742012-07-17 18:30:30 -0700799 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500800 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
801 */
802 protected void handleUserSwitchComplete(int userId) {
803 for (int i = 0; i < mCallbacks.size(); i++) {
804 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
805 if (cb != null) {
806 cb.onUserSwitchComplete(userId);
807 }
808 }
809 }
810
811 /**
Jim Miller90873d52013-09-26 18:11:38 -0700812 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
813 * keyguard crashes sometime after boot, then it will never receive this
814 * broadcast and hence not handle the event. This method is ultimately called by
815 * PhoneWindowManager in this case.
816 */
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100817 public void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700818 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -0700819 }
820
821 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800822 * Handle {@link #MSG_BOOT_COMPLETED}
823 */
824 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700825 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800826 mBootCompleted = true;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800827 for (int i = 0; i < mCallbacks.size(); i++) {
828 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
829 if (cb != null) {
830 cb.onBootCompleted();
831 }
832 }
833 }
834
835 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800836 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800837 * destroyed.
838 */
839 public boolean hasBootCompleted() {
840 return mBootCompleted;
841 }
842
843 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500844 * Handle {@link #MSG_USER_REMOVED}
Jim Millerbbf1a742012-07-17 18:30:30 -0700845 */
846 protected void handleUserRemoved(int userId) {
847 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700848 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
849 if (cb != null) {
850 cb.onUserRemoved(userId);
851 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700852 }
853 }
854
855 /**
856 * Handle {@link #MSG_DEVICE_PROVISIONED}
857 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700858 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700859 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700860 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
861 if (cb != null) {
862 cb.onDeviceProvisioned();
863 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700864 }
Michael Jurkafff56142012-11-28 16:51:00 -0800865 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700866 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800867 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
868 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700869 }
870 }
871
Jim Millerbbf1a742012-07-17 18:30:30 -0700872 /**
873 * Handle {@link #MSG_PHONE_STATE_CHANGED}
874 */
Jim Millerc23024d2010-02-24 15:37:00 -0800875 protected void handlePhoneStateChanged(String newState) {
876 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700877 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
878 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
879 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
880 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
881 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
882 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
883 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700884 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700885 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
886 if (cb != null) {
887 cb.onPhoneStateChanged(mPhoneState);
888 }
Jim Millerc23024d2010-02-24 15:37:00 -0800889 }
890 }
891
Jim Millerbbf1a742012-07-17 18:30:30 -0700892 /**
893 * Handle {@link #MSG_RINGER_MODE_CHANGED}
894 */
Jim Miller47088bb2009-11-24 00:40:16 -0800895 protected void handleRingerModeChange(int mode) {
896 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700897 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700898 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700899 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
900 if (cb != null) {
901 cb.onRingerModeChanged(mode);
902 }
Jim Miller47088bb2009-11-24 00:40:16 -0800903 }
904 }
905
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800906 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800907 * Handle {@link #MSG_TIME_UPDATE}
908 */
909 private void handleTimeUpdate() {
910 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700911 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700912 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
913 if (cb != null) {
914 cb.onTimeChanged();
915 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800916 }
917 }
918
919 /**
920 * Handle {@link #MSG_BATTERY_UPDATE}
921 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700922 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800923 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700924 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
925 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700926 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700927 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700928 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
929 if (cb != null) {
930 cb.onRefreshBatteryInfo(status);
931 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800932 }
933 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800934 }
935
936 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800937 * Handle {@link #MSG_SIM_STATE_CHANGE}
938 */
Jim Miller52a61332014-11-12 19:29:51 -0800939 private void handleSimStateChange(int subId, int slotId, State state) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800940
Jim Miller52a61332014-11-12 19:29:51 -0800941 if (DEBUG_SIM_STATES) {
942 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
943 + slotId + ", state=" + state +")");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800944 }
945
Wink Savillea54bf652014-12-11 13:37:50 -0800946 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Jim Miller52a61332014-11-12 19:29:51 -0800947 Log.w(TAG, "invalid subId in handleSimStateChange()");
948 return;
949 }
950
951 SimData data = mSimDatas.get(subId);
952 final boolean changed;
953 if (data == null) {
954 data = new SimData(state, slotId, subId);
955 mSimDatas.put(subId, data);
956 changed = true; // no data yet; force update
957 } else {
958 changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
959 data.simState = state;
960 data.subId = subId;
961 data.slotId = slotId;
962 }
963 if (changed && state != State.UNKNOWN) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700964 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700965 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
966 if (cb != null) {
Jim Miller52a61332014-11-12 19:29:51 -0800967 cb.onSimStateChanged(subId, slotId, state);
Jim Millerdcb3d842012-08-23 19:18:12 -0700968 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800969 }
970 }
971 }
972
Jim Millerbbf1a742012-07-17 18:30:30 -0700973 /**
974 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
975 */
Jeff Sharkey054340d2011-09-01 22:28:03 -0700976 private void handleClockVisibilityChanged() {
977 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
Jim Millerbbf1a742012-07-17 18:30:30 -0700978 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700979 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
980 if (cb != null) {
981 cb.onClockVisibilityChanged();
982 }
Jeff Sharkey054340d2011-09-01 22:28:03 -0700983 }
984 }
985
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400986 /**
987 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
988 */
989 private void handleKeyguardVisibilityChanged(int showing) {
990 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -0400991 boolean isShowing = (showing == 1);
992 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400993 for (int i = 0; i < mCallbacks.size(); i++) {
994 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
995 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -0400996 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400997 }
998 }
999 }
1000
Brian Colonna7fce3802013-09-17 15:51:32 -04001001 /**
Adrian Roosb6011622014-05-14 15:52:53 +02001002 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
1003 * @see #sendKeyguardBouncerChanged(boolean)
1004 */
1005 private void handleKeyguardBouncerChanged(int bouncer) {
1006 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
1007 boolean isBouncer = (bouncer == 1);
1008 mBouncer = isBouncer;
1009 for (int i = 0; i < mCallbacks.size(); i++) {
1010 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1011 if (cb != null) {
1012 cb.onKeyguardBouncerChanged(isBouncer);
1013 }
1014 }
1015 }
1016
1017 /**
Brian Colonna7fce3802013-09-17 15:51:32 -04001018 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
1019 */
1020 private void handleReportEmergencyCallAction() {
1021 for (int i = 0; i < mCallbacks.size(); i++) {
1022 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
1023 if (cb != null) {
1024 cb.onEmergencyCallAction();
1025 }
1026 }
1027 }
1028
Danielle Millett5d2404d2012-11-01 00:05:27 -04001029 public boolean isKeyguardVisible() {
1030 return mKeyguardIsVisible;
1031 }
1032
Adrian Roosb6011622014-05-14 15:52:53 +02001033 /**
1034 * @return if the keyguard is currently in bouncer mode.
1035 */
1036 public boolean isKeyguardBouncer() {
1037 return mBouncer;
1038 }
1039
Brian Colonnaa5239892013-04-15 11:45:40 -04001040 public boolean isSwitchingUser() {
1041 return mSwitchingUser;
1042 }
1043
Jim Miller16464b82011-10-20 21:10:13 -07001044 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -07001045 final boolean nowPluggedIn = current.isPluggedIn();
1046 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -08001047 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -07001048 wasPluggedIn == true && nowPluggedIn == true
1049 && (old.status != current.status);
1050
1051 // change in plug state is always interesting
1052 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001053 return true;
1054 }
1055
1056 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -07001057 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001058 return true;
1059 }
1060
Jim Miller16464b82011-10-20 21:10:13 -07001061 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -07001062 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -07001063 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001064 }
1065 return false;
1066 }
1067
1068 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001069 * @return The default plmn (no service)
1070 */
1071 private CharSequence getDefaultPlmn() {
Jim Miller5ecd8112013-01-09 18:50:26 -08001072 return mContext.getResources().getText(R.string.keyguard_carrier_default);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001073 }
1074
1075 /**
Jim Millerbbf1a742012-07-17 18:30:30 -07001076 * Remove the given observer's callback.
1077 *
Jim Miller6212cc02012-09-05 17:35:31 -07001078 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001079 */
Jim Miller6212cc02012-09-05 17:35:31 -07001080 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1081 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1082 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1083 if (mCallbacks.get(i).get() == callback) {
1084 mCallbacks.remove(i);
1085 }
1086 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001087 }
1088
1089 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001090 * Register to receive notifications about general keyguard information
1091 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -07001092 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001093 */
Jim Millerbbf1a742012-07-17 18:30:30 -07001094 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -07001095 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1096 // Prevent adding duplicate callbacks
1097 for (int i = 0; i < mCallbacks.size(); i++) {
1098 if (mCallbacks.get(i).get() == callback) {
1099 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1100 new Exception("Called by"));
1101 return;
Jim Millerdcb3d842012-08-23 19:18:12 -07001102 }
1103 }
Jim Miller6212cc02012-09-05 17:35:31 -07001104 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1105 removeCallback(null); // remove unused references
1106 sendUpdates(callback);
1107 }
1108
1109 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1110 // Notify listener of the current state
1111 callback.onRefreshBatteryInfo(mBatteryStatus);
1112 callback.onTimeChanged();
1113 callback.onRingerModeChanged(mRingMode);
1114 callback.onPhoneStateChanged(mPhoneState);
Jason Monk9ff69bd2014-12-02 16:43:17 -05001115 callback.onRefreshCarrierInfo();
Jim Miller6212cc02012-09-05 17:35:31 -07001116 callback.onClockVisibilityChanged();
Jim Miller52a61332014-11-12 19:29:51 -08001117 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
1118 final SimData state = data.getValue();
1119 callback.onSimStateChanged(state.subId, state.slotId, state.simState);
1120 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001121 }
1122
Danielle Millettf6d0fc12012-10-23 16:16:52 -04001123 public void sendKeyguardVisibilityChanged(boolean showing) {
1124 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1125 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1126 message.arg1 = showing ? 1 : 0;
1127 message.sendToTarget();
1128 }
1129
Adrian Roosb6011622014-05-14 15:52:53 +02001130 /**
1131 * @see #handleKeyguardBouncerChanged(int)
1132 */
1133 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1134 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1135 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1136 message.arg1 = showingBouncer ? 1 : 0;
1137 message.sendToTarget();
1138 }
1139
Jeff Sharkey054340d2011-09-01 22:28:03 -07001140 public void reportClockVisible(boolean visible) {
1141 mClockVisible = visible;
1142 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
1143 }
1144
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001145 /**
Jim Miller90d5d462011-11-17 16:57:01 -08001146 * 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 -08001147 * have the information earlier than waiting for the intent
1148 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -08001149 *
1150 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1151 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001152 */
Jim Miller52a61332014-11-12 19:29:51 -08001153 public void reportSimUnlocked(int subId) {
1154 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
1155 int slotId = SubscriptionManager.getSlotId(subId);
1156 handleSimStateChange(subId, slotId, State.READY);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001157 }
1158
Brian Colonna7fce3802013-09-17 15:51:32 -04001159 /**
1160 * Report that the emergency call button has been pressed and the emergency dialer is
1161 * about to be displayed.
1162 *
1163 * @param bypassHandler runs immediately.
1164 *
1165 * NOTE: Must be called from UI thread if bypassHandler == true.
1166 */
1167 public void reportEmergencyCallAction(boolean bypassHandler) {
1168 if (!bypassHandler) {
1169 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1170 } else {
1171 handleReportEmergencyCallAction();
1172 }
1173 }
1174
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001175 /**
1176 * @return Whether the device is provisioned (whether they have gone through
1177 * the setup wizard)
1178 */
1179 public boolean isDeviceProvisioned() {
1180 return mDeviceProvisioned;
1181 }
1182
Jim Miller258341c2012-08-30 16:50:10 -07001183 public int getFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001184 return mFailedAttempts;
1185 }
1186
Jim Miller258341c2012-08-30 16:50:10 -07001187 public void clearFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001188 mFailedAttempts = 0;
Brian Colonnaea8441e2012-04-25 17:51:49 -04001189 mFailedBiometricUnlockAttempts = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001190 }
1191
Jim Millerf41fc962014-06-18 16:33:51 -07001192 public void clearFingerprintRecognized() {
1193 mUserFingerprintRecognized.clear();
1194 }
1195
Jim Miller258341c2012-08-30 16:50:10 -07001196 public void reportFailedUnlockAttempt() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001197 mFailedAttempts++;
1198 }
Jim Miller1c188282011-08-08 22:27:58 -07001199
Jeff Sharkey054340d2011-09-01 22:28:03 -07001200 public boolean isClockVisible() {
1201 return mClockVisible;
1202 }
1203
Brian Colonna267cb2b2011-09-26 13:52:25 -04001204 public int getPhoneState() {
1205 return mPhoneState;
1206 }
Steven Rossb9430d22011-11-23 07:54:09 -05001207
Brian Colonnaea8441e2012-04-25 17:51:49 -04001208 public void reportFailedBiometricUnlockAttempt() {
1209 mFailedBiometricUnlockAttempts++;
Steven Rossb9430d22011-11-23 07:54:09 -05001210 }
1211
Brian Colonnaea8441e2012-04-25 17:51:49 -04001212 public boolean getMaxBiometricUnlockAttemptsReached() {
1213 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
Steven Rossb9430d22011-11-23 07:54:09 -05001214 }
Jim Millerb0304762012-03-13 20:01:25 -07001215
Jim Miller0ff7f012012-10-11 20:40:01 -07001216 public boolean isAlternateUnlockEnabled() {
1217 return mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001218 }
1219
Jim Miller0ff7f012012-10-11 20:40:01 -07001220 public void setAlternateUnlockEnabled(boolean enabled) {
1221 mAlternateUnlockEnabled = enabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001222 }
1223
Jim Miller52a61332014-11-12 19:29:51 -08001224 public boolean isSimPinVoiceSecure() {
1225 // TODO: only count SIMs that handle voice
1226 return isSimPinSecure();
Jim Millerdcb3d842012-08-23 19:18:12 -07001227 }
1228
1229 public boolean isSimPinSecure() {
Jim Miller52a61332014-11-12 19:29:51 -08001230 // True if any SIM is pin secure
1231 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
1232 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
1233 }
1234 return false;
1235 }
1236
Jason Monk9ff69bd2014-12-02 16:43:17 -05001237 public State getSimState(int subId) {
Jim Miller52a61332014-11-12 19:29:51 -08001238 if (mSimDatas.containsKey(subId)) {
1239 return mSimDatas.get(subId).simState;
1240 } else {
1241 return State.UNKNOWN;
1242 }
1243 }
1244
1245 private void refreshSimState(int subId, int slotId) {
1246
1247 // This is awful. It exists because there are two APIs for getting the SIM status
1248 // that don't return the complete set of values and have different types. In Keyguard we
1249 // need IccCardConstants, but TelephonyManager would only give us
1250 // TelephonyManager.SIM_STATE*, so we retrieve it manually.
xinhe18b9c3c2014-12-02 15:03:20 -08001251 final TelephonyManager tele = TelephonyManager.from(mContext);
1252 int simState = tele.getSimState(slotId);
Jim Miller52a61332014-11-12 19:29:51 -08001253 State state;
1254 try {
xinhe18b9c3c2014-12-02 15:03:20 -08001255 state = State.intToState(simState);
Jim Miller52a61332014-11-12 19:29:51 -08001256 } catch(IllegalArgumentException ex) {
xinhe18b9c3c2014-12-02 15:03:20 -08001257 Log.w(TAG, "Unknown sim state: " + simState);
Jim Miller52a61332014-11-12 19:29:51 -08001258 state = State.UNKNOWN;
xinhe18b9c3c2014-12-02 15:03:20 -08001259 }
Jim Miller52a61332014-11-12 19:29:51 -08001260 mSimDatas.put(subId, new SimData(state, slotId, subId));
Jim Millerdcb3d842012-08-23 19:18:12 -07001261 }
1262
1263 public static boolean isSimPinSecure(IccCardConstants.State state) {
1264 final IccCardConstants.State simState = state;
1265 return (simState == IccCardConstants.State.PIN_REQUIRED
1266 || simState == IccCardConstants.State.PUK_REQUIRED
1267 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001268 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001269
1270 public DisplayClientState getCachedDisplayClientState() {
1271 return mDisplayClientState;
1272 }
Jim Miller20daffd2013-10-07 14:59:53 -07001273
1274 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1275 // (KeyguardViewMediator, KeyguardHostView)
1276 public void dispatchScreenTurnedOn() {
1277 synchronized (this) {
1278 mScreenOn = true;
1279 }
1280 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1281 }
1282
1283 public void dispatchScreenTurndOff(int why) {
1284 synchronized(this) {
1285 mScreenOn = false;
1286 }
1287 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1288 }
1289
1290 public boolean isScreenOn() {
1291 return mScreenOn;
1292 }
Jim Miller52a61332014-11-12 19:29:51 -08001293
1294 /**
1295 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
1296 * @param state
Wink Savilled09c4ca2014-11-22 10:08:16 -08001297 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
Jim Miller52a61332014-11-12 19:29:51 -08001298 */
1299 public int getNextSubIdForState(State state) {
1300 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
Wink Savilled09c4ca2014-11-22 10:08:16 -08001301 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Jim Miller52a61332014-11-12 19:29:51 -08001302 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
1303 for (int i = 0; i < list.size(); i++) {
1304 final SubscriptionInfo info = list.get(i);
1305 final int id = info.getSubscriptionId();
1306 int slotId = SubscriptionManager.getSlotId(id);
1307 if (state == getSimState(id) && bestSlotId > slotId ) {
1308 resultId = id;
1309 bestSlotId = slotId;
1310 }
1311 }
1312 return resultId;
1313 }
1314
1315 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) {
1316 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
1317 for (int i = 0; i < list.size(); i++) {
1318 SubscriptionInfo info = list.get(i);
1319 if (subId == info.getSubscriptionId()) return info;
1320 }
1321 return null; // not found
1322 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001323}