blob: a8493166ac847ff37d53d54559cf91a9fbfb56b7 [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;
20import android.app.IUserSwitchObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070021import android.app.PendingIntent;
Jim Millerb0304762012-03-13 20:01:25 -070022import android.app.admin.DevicePolicyManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080023import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080027import android.database.ContentObserver;
Jim Miller8f09fd22013-03-14 19:04:28 -070028import android.graphics.Bitmap;
29
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080030import static android.os.BatteryManager.BATTERY_STATUS_FULL;
31import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
Jim Miller16464b82011-10-20 21:10:13 -070032import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
33import static android.os.BatteryManager.EXTRA_STATUS;
34import static android.os.BatteryManager.EXTRA_PLUGGED;
35import static android.os.BatteryManager.EXTRA_LEVEL;
36import static android.os.BatteryManager.EXTRA_HEALTH;
Jim Miller47088bb2009-11-24 00:40:16 -080037import android.media.AudioManager;
Jim Miller8f09fd22013-03-14 19:04:28 -070038import android.media.IRemoteControlDisplay;
Jim Miller79a444a2011-02-15 15:02:11 -080039import android.os.BatteryManager;
Jim Miller8f09fd22013-03-14 19:04:28 -070040import android.os.Bundle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080041import android.os.Handler;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070042import android.os.IRemoteCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080043import android.os.Message;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070044import android.os.RemoteException;
Amith Yamasanie8e93a12013-05-09 18:12:30 -070045import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080046import android.provider.Settings;
Dianne Hackbornb7e787f2009-05-07 15:55:42 -070047
Wink Savillea639b312012-07-10 12:37:54 -070048import com.android.internal.telephony.IccCardConstants;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080049import com.android.internal.telephony.TelephonyIntents;
Jim Millerc23024d2010-02-24 15:37:00 -080050
51import android.telephony.TelephonyManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080052import android.util.Log;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080053import com.google.android.collect.Lists;
54
Jim Millerdcb3d842012-08-23 19:18:12 -070055import java.lang.ref.WeakReference;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080056import java.util.ArrayList;
57
58/**
59 * Watches for updates that may be interesting to the keyguard, and provides
60 * the up to date information as well as a registration for callbacks that care
61 * to be updated.
62 *
63 * Note: under time crunch, this has been extended to include some stuff that
64 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
Jim Miller258341c2012-08-30 16:50:10 -070065 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
66 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080067 */
68public class KeyguardUpdateMonitor {
69
Jim Millerbbf1a742012-07-17 18:30:30 -070070 private static final String TAG = "KeyguardUpdateMonitor";
71 private static final boolean DEBUG = false;
72 private static final boolean DEBUG_SIM_STATES = DEBUG || false;
Uriel Rodriguezaa249062012-06-13 17:30:13 -040073 private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
Jim Millerbbf1a742012-07-17 18:30:30 -070074 private static final int LOW_BATTERY_THRESHOLD = 20;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080075
Jim Millerbbf1a742012-07-17 18:30:30 -070076 // Callback messages
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080077 private static final int MSG_TIME_UPDATE = 301;
78 private static final int MSG_BATTERY_UPDATE = 302;
79 private static final int MSG_CARRIER_INFO_UPDATE = 303;
80 private static final int MSG_SIM_STATE_CHANGE = 304;
Jim Miller47088bb2009-11-24 00:40:16 -080081 private static final int MSG_RINGER_MODE_CHANGED = 305;
Jim Millerc23024d2010-02-24 15:37:00 -080082 private static final int MSG_PHONE_STATE_CHANGED = 306;
Jeff Sharkey054340d2011-09-01 22:28:03 -070083 private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
Nick Pelly24d7b5f2011-10-11 12:51:09 -070084 private static final int MSG_DEVICE_PROVISIONED = 308;
Jim Miller57375342012-09-09 15:20:31 -070085 private static final int MSG_DPM_STATE_CHANGED = 309;
Chris Wrenf41c61b2012-11-29 15:19:54 -050086 private static final int MSG_USER_SWITCHING = 310;
Jim Miller57375342012-09-09 15:20:31 -070087 private static final int MSG_USER_REMOVED = 311;
Danielle Millettf6d0fc12012-10-23 16:16:52 -040088 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
Adam Cohenefb3ffb2012-11-06 16:55:32 -080089 protected static final int MSG_BOOT_COMPLETED = 313;
Chris Wrenf41c61b2012-11-29 15:19:54 -050090 private static final int MSG_USER_SWITCH_COMPLETE = 314;
Jim Miller8f09fd22013-03-14 19:04:28 -070091 private static final int MSG_SET_CURRENT_CLIENT_ID = 315;
92 protected static final int MSG_SET_PLAYBACK_STATE = 316;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -070093 protected static final int MSG_USER_INFO_CHANGED = 317;
Brian Colonna7fce3802013-09-17 15:51:32 -040094 protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
Jim Miller20daffd2013-10-07 14:59:53 -070095 private static final int MSG_SCREEN_TURNED_ON = 319;
96 private static final int MSG_SCREEN_TURNED_OFF = 320;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080097
Jim Millerdcb3d842012-08-23 19:18:12 -070098 private static KeyguardUpdateMonitor sInstance;
99
Jim Millerbbf1a742012-07-17 18:30:30 -0700100 private final Context mContext;
101
102 // Telephony state
103 private IccCardConstants.State mSimState = IccCardConstants.State.READY;
104 private CharSequence mTelephonyPlmn;
105 private CharSequence mTelephonySpn;
106 private int mRingMode;
107 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400108 private boolean mKeyguardIsVisible;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800109 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700110
Jim Millerdcb3d842012-08-23 19:18:12 -0700111 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700112 private boolean mDeviceProvisioned;
113
Jim Millerdcb3d842012-08-23 19:18:12 -0700114 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700115 private BatteryStatus mBatteryStatus;
116
Jim Millerdcb3d842012-08-23 19:18:12 -0700117 // Password attempts
Jim Millerbbf1a742012-07-17 18:30:30 -0700118 private int mFailedAttempts = 0;
119 private int mFailedBiometricUnlockAttempts = 0;
120
Jim Miller0ff7f012012-10-11 20:40:01 -0700121 private boolean mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400122
Jim Millerbbf1a742012-07-17 18:30:30 -0700123 private boolean mClockVisible;
124
Jim Miller6212cc02012-09-05 17:35:31 -0700125 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700126 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800127 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700128
Brian Colonnaa5239892013-04-15 11:45:40 -0400129 private boolean mSwitchingUser;
130
Jim Miller20daffd2013-10-07 14:59:53 -0700131 private boolean mScreenOn;
132
Jim Millerbbf1a742012-07-17 18:30:30 -0700133 private final Handler mHandler = new Handler() {
134 @Override
135 public void handleMessage(Message msg) {
136 switch (msg.what) {
137 case MSG_TIME_UPDATE:
138 handleTimeUpdate();
139 break;
140 case MSG_BATTERY_UPDATE:
141 handleBatteryUpdate((BatteryStatus) msg.obj);
142 break;
143 case MSG_CARRIER_INFO_UPDATE:
144 handleCarrierInfoUpdate();
145 break;
146 case MSG_SIM_STATE_CHANGE:
147 handleSimStateChange((SimArgs) msg.obj);
148 break;
149 case MSG_RINGER_MODE_CHANGED:
150 handleRingerModeChange(msg.arg1);
151 break;
152 case MSG_PHONE_STATE_CHANGED:
153 handlePhoneStateChanged((String)msg.obj);
154 break;
155 case MSG_CLOCK_VISIBILITY_CHANGED:
156 handleClockVisibilityChanged();
157 break;
158 case MSG_DEVICE_PROVISIONED:
159 handleDeviceProvisioned();
160 break;
161 case MSG_DPM_STATE_CHANGED:
162 handleDevicePolicyManagerStateChanged();
163 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500164 case MSG_USER_SWITCHING:
165 handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
166 break;
167 case MSG_USER_SWITCH_COMPLETE:
168 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700169 break;
170 case MSG_USER_REMOVED:
171 handleUserRemoved(msg.arg1);
172 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400173 case MSG_KEYGUARD_VISIBILITY_CHANGED:
174 handleKeyguardVisibilityChanged(msg.arg1);
175 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800176 case MSG_BOOT_COMPLETED:
177 handleBootCompleted();
178 break;
Jim Miller8f09fd22013-03-14 19:04:28 -0700179 case MSG_SET_CURRENT_CLIENT_ID:
180 handleSetGenerationId(msg.arg1, msg.arg2 != 0, (PendingIntent) msg.obj);
181 break;
182 case MSG_SET_PLAYBACK_STATE:
183 handleSetPlaybackState(msg.arg1, msg.arg2, (Long) msg.obj);
184 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700185 case MSG_USER_INFO_CHANGED:
186 handleUserInfoChanged(msg.arg1);
187 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400188 case MSG_REPORT_EMERGENCY_CALL_ACTION:
189 handleReportEmergencyCallAction();
190 break;
Jim Miller20daffd2013-10-07 14:59:53 -0700191 case MSG_SCREEN_TURNED_OFF:
192 handleScreenTurnedOff(msg.arg1);
193 break;
194 case MSG_SCREEN_TURNED_ON:
195 handleScreenTurnedOn();
196 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700197 }
198 }
199 };
200
Jim Miller8f09fd22013-03-14 19:04:28 -0700201 private AudioManager mAudioManager;
202
203 static class DisplayClientState {
204 public int clientGeneration;
205 public boolean clearing;
206 public PendingIntent intent;
207 public int playbackState;
208 public long playbackEventTime;
209 }
210
211 private DisplayClientState mDisplayClientState = new DisplayClientState();
212
213 /**
214 * This currently implements the bare minimum required to enable showing and hiding
215 * KeyguardTransportControl. There's a lot of client state to maintain which is why
216 * KeyguardTransportControl maintains an independent connection while it's showing.
217 */
218 private final IRemoteControlDisplay.Stub mRemoteControlDisplay =
219 new IRemoteControlDisplay.Stub() {
220
Jean-Michel Trivibc43b4c2013-03-22 09:30:50 -0700221 public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
222 long currentPosMs, float speed) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700223 Message msg = mHandler.obtainMessage(MSG_SET_PLAYBACK_STATE,
224 generationId, state, stateChangeTimeMs);
225 mHandler.sendMessage(msg);
226 }
227
228 public void setMetadata(int generationId, Bundle metadata) {
229
230 }
231
Jean-Michel Trivi3261b532013-04-01 14:59:39 -0700232 public void setTransportControlInfo(int generationId, int flags, int posCapabilities) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700233
234 }
235
236 public void setArtwork(int generationId, Bitmap bitmap) {
237
238 }
239
240 public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
241
242 }
243
Jean-Michel Trivif108cdd92013-09-27 18:37:36 -0700244 public void setEnabled(boolean enabled) {
245 // no-op: this RemoteControlDisplay is not subject to being disabled.
246 }
247
Jim Miller8f09fd22013-03-14 19:04:28 -0700248 public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
249 boolean clearing) throws RemoteException {
250 Message msg = mHandler.obtainMessage(MSG_SET_CURRENT_CLIENT_ID,
251 clientGeneration, (clearing ? 1 : 0), mediaIntent);
252 mHandler.sendMessage(msg);
253 }
254 };
255
Jim Millerbbf1a742012-07-17 18:30:30 -0700256 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
257
258 public void onReceive(Context context, Intent intent) {
259 final String action = intent.getAction();
260 if (DEBUG) Log.d(TAG, "received broadcast " + action);
261
262 if (Intent.ACTION_TIME_TICK.equals(action)
263 || Intent.ACTION_TIME_CHANGED.equals(action)
264 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700265 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700266 } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
267 mTelephonyPlmn = getTelephonyPlmnFrom(intent);
268 mTelephonySpn = getTelephonySpnFrom(intent);
Jim Miller90873d52013-09-26 18:11:38 -0700269 mHandler.sendEmptyMessage(MSG_CARRIER_INFO_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700270 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
271 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
272 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
273 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
274 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
275 final Message msg = mHandler.obtainMessage(
276 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
277 mHandler.sendMessage(msg);
278 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
279 if (DEBUG_SIM_STATES) {
280 Log.v(TAG, "action " + action + " state" +
281 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
282 }
283 mHandler.sendMessage(mHandler.obtainMessage(
284 MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
285 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
286 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
287 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
288 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
289 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
290 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
291 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
292 .equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700293 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700294 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
295 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
Jim Millerdcb3d842012-08-23 19:18:12 -0700296 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800297 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700298 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700299 }
300 }
301 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700302
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700303 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
304
305 public void onReceive(Context context, Intent intent) {
306 final String action = intent.getAction();
307 if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
308 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
309 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
310 }
311 }
312 };
313
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800314 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800315 * When we receive a
316 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700317 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800318 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800319 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800320 */
321 private static class SimArgs {
Wink Savillea639b312012-07-10 12:37:54 -0700322 public final IccCardConstants.State simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800323
Wink Savillea639b312012-07-10 12:37:54 -0700324 SimArgs(IccCardConstants.State state) {
Jim Miller90d5d462011-11-17 16:57:01 -0800325 simState = state;
326 }
327
328 static SimArgs fromIntent(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700329 IccCardConstants.State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800330 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
331 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
332 }
Wink Savillea639b312012-07-10 12:37:54 -0700333 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
334 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700335 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700336 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700337
Wink Savillea639b312012-07-10 12:37:54 -0700338 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700339 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700340 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700341 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700342 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700343 }
Wink Savillea639b312012-07-10 12:37:54 -0700344 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
345 state = IccCardConstants.State.READY;
346 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800347 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700348 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
349 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
350 state = IccCardConstants.State.PIN_REQUIRED;
351 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
352 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800353 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700354 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800355 }
Wink Savillea639b312012-07-10 12:37:54 -0700356 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
357 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700358 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
359 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
360 // This is required because telephony doesn't return to "READY" after
361 // these state transitions. See bug 7197471.
362 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800363 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700364 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800365 }
Jim Miller90d5d462011-11-17 16:57:01 -0800366 return new SimArgs(state);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800367 }
368
369 public String toString() {
370 return simState.toString();
371 }
372 }
373
Jim Millerbbf1a742012-07-17 18:30:30 -0700374 /* package */ static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700375 public final int status;
376 public final int level;
377 public final int plugged;
378 public final int health;
379 public BatteryStatus(int status, int level, int plugged, int health) {
380 this.status = status;
381 this.level = level;
382 this.plugged = plugged;
383 this.health = health;
384 }
385
Jim Millerbbf1a742012-07-17 18:30:30 -0700386 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700387 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700388 * @return true if the device is plugged in.
389 */
390 boolean isPluggedIn() {
391 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700392 || plugged == BatteryManager.BATTERY_PLUGGED_USB
393 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700394 }
395
396 /**
397 * Whether or not the device is charged. Note that some devices never return 100% for
398 * battery level, so this allows either battery level or status to determine if the
399 * battery is charged.
400 * @return true if the device is charged
401 */
402 public boolean isCharged() {
403 return status == BATTERY_STATUS_FULL || level >= 100;
404 }
405
406 /**
407 * Whether battery is low and needs to be charged.
408 * @return true if battery is low
409 */
410 public boolean isBatteryLow() {
411 return level < LOW_BATTERY_THRESHOLD;
412 }
413
Jim Miller16464b82011-10-20 21:10:13 -0700414 }
415
Jim Millerdcb3d842012-08-23 19:18:12 -0700416 public static KeyguardUpdateMonitor getInstance(Context context) {
417 if (sInstance == null) {
418 sInstance = new KeyguardUpdateMonitor(context);
419 }
420 return sInstance;
421 }
422
Jim Miller20daffd2013-10-07 14:59:53 -0700423 protected void handleScreenTurnedOn() {
424 final int count = mCallbacks.size();
425 for (int i = 0; i < count; i++) {
426 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
427 if (cb != null) {
428 cb.onScreenTurnedOn();
429 }
430 }
431 }
432
433 protected void handleScreenTurnedOff(int arg1) {
434 final int count = mCallbacks.size();
435 for (int i = 0; i < count; i++) {
436 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
437 if (cb != null) {
438 cb.onScreenTurnedOff(arg1);
439 }
440 }
441 }
442
Adam Powell43a372f2013-09-27 17:43:53 -0700443 /**
444 * IMPORTANT: Must be called from UI thread.
445 */
446 public void dispatchSetBackground(Bitmap bmp) {
447 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
448 final int count = mCallbacks.size();
449 for (int i = 0; i < count; i++) {
450 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
451 if (cb != null) {
452 cb.onSetBackground(bmp);
453 }
454 }
455 }
456
Jim Miller8f09fd22013-03-14 19:04:28 -0700457 protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) {
458 mDisplayClientState.clientGeneration = clientGeneration;
459 mDisplayClientState.clearing = clearing;
460 mDisplayClientState.intent = p;
Jim Miller4894a012013-04-03 15:23:55 -0700461 if (DEBUG)
462 Log.v(TAG, "handleSetGenerationId(g=" + clientGeneration + ", clear=" + clearing + ")");
Jim Miller8f09fd22013-03-14 19:04:28 -0700463 for (int i = 0; i < mCallbacks.size(); i++) {
464 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
465 if (cb != null) {
466 cb.onMusicClientIdChanged(clientGeneration, clearing, p);
467 }
468 }
469 }
470
471 protected void handleSetPlaybackState(int generationId, int playbackState, long eventTime) {
Jim Miller4894a012013-04-03 15:23:55 -0700472 if (DEBUG)
473 Log.v(TAG, "handleSetPlaybackState(gen=" + generationId
474 + ", state=" + playbackState + ", t=" + eventTime + ")");
475 mDisplayClientState.playbackState = playbackState;
476 mDisplayClientState.playbackEventTime = eventTime;
Jim Miller8f09fd22013-03-14 19:04:28 -0700477 if (generationId == mDisplayClientState.clientGeneration) {
478 for (int i = 0; i < mCallbacks.size(); i++) {
479 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
480 if (cb != null) {
481 cb.onMusicPlaybackStateChanged(playbackState, eventTime);
482 }
483 }
484 } else {
485 Log.w(TAG, "Ignoring generation id " + generationId + " because it's not current");
486 }
487 }
488
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700489 private void handleUserInfoChanged(int userId) {
490 for (int i = 0; i < mCallbacks.size(); i++) {
491 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
492 if (cb != null) {
493 cb.onUserInfoChanged(userId);
494 }
495 }
496 }
497
Jim Millerdcb3d842012-08-23 19:18:12 -0700498 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800499 mContext = context;
Jim Miller47088bb2009-11-24 00:40:16 -0800500
Michael Jurkafff56142012-11-28 16:51:00 -0800501 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800502 // Since device can't be un-provisioned, we only need to register a content observer
503 // to update mDeviceProvisioned when we are...
504 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700505 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800506 }
Jim Miller47088bb2009-11-24 00:40:16 -0800507
Jim Millerbbf1a742012-07-17 18:30:30 -0700508 // Take a guess at initial SIM state, battery status and PLMN until we get an update
509 mSimState = IccCardConstants.State.NOT_READY;
Jim Miller16464b82011-10-20 21:10:13 -0700510 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800511 mTelephonyPlmn = getDefaultPlmn();
512
Jim Millerbbf1a742012-07-17 18:30:30 -0700513 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800514 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800515 filter.addAction(Intent.ACTION_TIME_TICK);
516 filter.addAction(Intent.ACTION_TIME_CHANGED);
517 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
518 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
519 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800520 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Wink Savillea639b312012-07-10 12:37:54 -0700521 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Jim Miller47088bb2009-11-24 00:40:16 -0800522 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerb0304762012-03-13 20:01:25 -0700523 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700524 filter.addAction(Intent.ACTION_USER_REMOVED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700525 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700526
Adam Cohenc276e822012-11-08 13:01:08 -0800527 final IntentFilter bootCompleteFilter = new IntentFilter();
528 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
529 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
530 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
531
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700532 final IntentFilter userInfoFilter = new IntentFilter(Intent.ACTION_USER_INFO_CHANGED);
533 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, userInfoFilter,
534 null, null);
535
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700536 try {
537 ActivityManagerNative.getDefault().registerUserSwitchObserver(
538 new IUserSwitchObserver.Stub() {
539 @Override
540 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500541 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700542 newUserId, 0, reply));
Brian Colonnaa5239892013-04-15 11:45:40 -0400543 mSwitchingUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700544 }
545 @Override
546 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500547 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
548 newUserId));
Brian Colonnaa5239892013-04-15 11:45:40 -0400549 mSwitchingUser = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700550 }
551 });
552 } catch (RemoteException e) {
553 // TODO Auto-generated catch block
554 e.printStackTrace();
555 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700556 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800557
Michael Jurkafff56142012-11-28 16:51:00 -0800558 private boolean isDeviceProvisionedInSettingsDb() {
559 return Settings.Global.getInt(mContext.getContentResolver(),
560 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
561 }
562
Jim Millerbbf1a742012-07-17 18:30:30 -0700563 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800564 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700565 @Override
566 public void onChange(boolean selfChange) {
567 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800568 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700569 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700570 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800571 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700572 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800573 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700574 };
575
576 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700577 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800578 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700579
580 // prevent a race condition between where we check the flag and where we register the
581 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800582 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700583 if (provisioned != mDeviceProvisioned) {
584 mDeviceProvisioned = provisioned;
585 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700586 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700587 }
588 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800589 }
590
Jim Millerbbf1a742012-07-17 18:30:30 -0700591 /**
592 * Handle {@link #MSG_DPM_STATE_CHANGED}
593 */
Jim Millerb0304762012-03-13 20:01:25 -0700594 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700595 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
596 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
597 if (cb != null) {
598 cb.onDevicePolicyManagerStateChanged();
599 }
Jim Millerb0304762012-03-13 20:01:25 -0700600 }
601 }
602
Jim Millerbbf1a742012-07-17 18:30:30 -0700603 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500604 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700605 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500606 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700607 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700608 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
609 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500610 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700611 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700612 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700613 try {
614 reply.sendResult(null);
615 } catch (RemoteException e) {
616 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700617 }
618
Jim Millerbbf1a742012-07-17 18:30:30 -0700619 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500620 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
621 */
622 protected void handleUserSwitchComplete(int userId) {
623 for (int i = 0; i < mCallbacks.size(); i++) {
624 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
625 if (cb != null) {
626 cb.onUserSwitchComplete(userId);
627 }
628 }
629 }
630
631 /**
Jim Miller90873d52013-09-26 18:11:38 -0700632 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
633 * keyguard crashes sometime after boot, then it will never receive this
634 * broadcast and hence not handle the event. This method is ultimately called by
635 * PhoneWindowManager in this case.
636 */
637 protected void dispatchBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700638 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
Jim Miller90873d52013-09-26 18:11:38 -0700639 }
640
641 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800642 * Handle {@link #MSG_BOOT_COMPLETED}
643 */
644 protected void handleBootCompleted() {
Jim Millere5f910a2013-10-16 18:15:46 -0700645 if (mBootCompleted) return;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800646 mBootCompleted = true;
Jim Miller8f09fd22013-03-14 19:04:28 -0700647 mAudioManager = new AudioManager(mContext);
648 mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800649 for (int i = 0; i < mCallbacks.size(); i++) {
650 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
651 if (cb != null) {
652 cb.onBootCompleted();
653 }
654 }
655 }
656
657 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800658 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800659 * destroyed.
660 */
661 public boolean hasBootCompleted() {
662 return mBootCompleted;
663 }
664
665 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500666 * Handle {@link #MSG_USER_REMOVED}
Jim Millerbbf1a742012-07-17 18:30:30 -0700667 */
668 protected void handleUserRemoved(int userId) {
669 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700670 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
671 if (cb != null) {
672 cb.onUserRemoved(userId);
673 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700674 }
675 }
676
677 /**
678 * Handle {@link #MSG_DEVICE_PROVISIONED}
679 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700680 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700681 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700682 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
683 if (cb != null) {
684 cb.onDeviceProvisioned();
685 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700686 }
Michael Jurkafff56142012-11-28 16:51:00 -0800687 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700688 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800689 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
690 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700691 }
692 }
693
Jim Millerbbf1a742012-07-17 18:30:30 -0700694 /**
695 * Handle {@link #MSG_PHONE_STATE_CHANGED}
696 */
Jim Millerc23024d2010-02-24 15:37:00 -0800697 protected void handlePhoneStateChanged(String newState) {
698 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700699 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
700 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
701 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
702 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
703 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
704 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
705 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700706 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700707 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
708 if (cb != null) {
709 cb.onPhoneStateChanged(mPhoneState);
710 }
Jim Millerc23024d2010-02-24 15:37:00 -0800711 }
712 }
713
Jim Millerbbf1a742012-07-17 18:30:30 -0700714 /**
715 * Handle {@link #MSG_RINGER_MODE_CHANGED}
716 */
Jim Miller47088bb2009-11-24 00:40:16 -0800717 protected void handleRingerModeChange(int mode) {
718 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700719 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700720 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700721 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
722 if (cb != null) {
723 cb.onRingerModeChanged(mode);
724 }
Jim Miller47088bb2009-11-24 00:40:16 -0800725 }
726 }
727
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800728 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800729 * Handle {@link #MSG_TIME_UPDATE}
730 */
731 private void handleTimeUpdate() {
732 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700733 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700734 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
735 if (cb != null) {
736 cb.onTimeChanged();
737 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800738 }
739 }
740
741 /**
742 * Handle {@link #MSG_BATTERY_UPDATE}
743 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700744 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800745 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700746 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
747 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700748 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700749 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700750 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
751 if (cb != null) {
752 cb.onRefreshBatteryInfo(status);
753 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800754 }
755 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800756 }
757
758 /**
759 * Handle {@link #MSG_CARRIER_INFO_UPDATE}
760 */
761 private void handleCarrierInfoUpdate() {
762 if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
763 + ", spn = " + mTelephonySpn);
764
Jim Millerbbf1a742012-07-17 18:30:30 -0700765 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700766 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
767 if (cb != null) {
768 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
769 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800770 }
771 }
772
773 /**
774 * Handle {@link #MSG_SIM_STATE_CHANGE}
775 */
776 private void handleSimStateChange(SimArgs simArgs) {
Wink Savillea639b312012-07-10 12:37:54 -0700777 final IccCardConstants.State state = simArgs.simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800778
779 if (DEBUG) {
780 Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
781 + "state resolved to " + state.toString());
782 }
783
Wink Savillea639b312012-07-10 12:37:54 -0700784 if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800785 mSimState = state;
Jim Millerbbf1a742012-07-17 18:30:30 -0700786 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700787 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
788 if (cb != null) {
789 cb.onSimStateChanged(state);
790 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800791 }
792 }
793 }
794
Jim Millerbbf1a742012-07-17 18:30:30 -0700795 /**
796 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
797 */
Jeff Sharkey054340d2011-09-01 22:28:03 -0700798 private void handleClockVisibilityChanged() {
799 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
Jim Millerbbf1a742012-07-17 18:30:30 -0700800 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700801 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
802 if (cb != null) {
803 cb.onClockVisibilityChanged();
804 }
Jeff Sharkey054340d2011-09-01 22:28:03 -0700805 }
806 }
807
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400808 /**
809 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
810 */
811 private void handleKeyguardVisibilityChanged(int showing) {
812 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -0400813 boolean isShowing = (showing == 1);
814 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400815 for (int i = 0; i < mCallbacks.size(); i++) {
816 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
817 if (cb != null) {
John Spurlock385a63d2013-10-30 19:40:48 -0400818 cb.onKeyguardVisibilityChangedRaw(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400819 }
820 }
821 }
822
Brian Colonna7fce3802013-09-17 15:51:32 -0400823 /**
824 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
825 */
826 private void handleReportEmergencyCallAction() {
827 for (int i = 0; i < mCallbacks.size(); i++) {
828 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
829 if (cb != null) {
830 cb.onEmergencyCallAction();
831 }
832 }
833 }
834
Danielle Millett5d2404d2012-11-01 00:05:27 -0400835 public boolean isKeyguardVisible() {
836 return mKeyguardIsVisible;
837 }
838
Brian Colonnaa5239892013-04-15 11:45:40 -0400839 public boolean isSwitchingUser() {
840 return mSwitchingUser;
841 }
842
Jim Miller16464b82011-10-20 21:10:13 -0700843 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700844 final boolean nowPluggedIn = current.isPluggedIn();
845 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -0800846 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -0700847 wasPluggedIn == true && nowPluggedIn == true
848 && (old.status != current.status);
849
850 // change in plug state is always interesting
851 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800852 return true;
853 }
854
855 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -0700856 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800857 return true;
858 }
859
Jim Miller16464b82011-10-20 21:10:13 -0700860 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -0700861 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -0700862 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800863 }
864 return false;
865 }
866
867 /**
Wink Savillea639b312012-07-10 12:37:54 -0700868 * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800869 * @return The string to use for the plmn, or null if it should not be shown.
870 */
871 private CharSequence getTelephonyPlmnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700872 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
873 final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
Jim Millerbbf1a742012-07-17 18:30:30 -0700874 return (plmn != null) ? plmn : getDefaultPlmn();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800875 }
876 return null;
877 }
878
879 /**
880 * @return The default plmn (no service)
881 */
882 private CharSequence getDefaultPlmn() {
Jim Miller5ecd8112013-01-09 18:50:26 -0800883 return mContext.getResources().getText(R.string.keyguard_carrier_default);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800884 }
885
886 /**
887 * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
888 * @return The string to use for the plmn, or null if it should not be shown.
889 */
890 private CharSequence getTelephonySpnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700891 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
892 final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800893 if (spn != null) {
894 return spn;
895 }
896 }
897 return null;
898 }
899
900 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700901 * Remove the given observer's callback.
902 *
Jim Miller6212cc02012-09-05 17:35:31 -0700903 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800904 */
Jim Miller6212cc02012-09-05 17:35:31 -0700905 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
906 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
907 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
908 if (mCallbacks.get(i).get() == callback) {
909 mCallbacks.remove(i);
910 }
911 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800912 }
913
914 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800915 * Register to receive notifications about general keyguard information
916 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -0700917 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800918 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700919 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -0700920 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
921 // Prevent adding duplicate callbacks
922 for (int i = 0; i < mCallbacks.size(); i++) {
923 if (mCallbacks.get(i).get() == callback) {
924 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
925 new Exception("Called by"));
926 return;
Jim Millerdcb3d842012-08-23 19:18:12 -0700927 }
928 }
Jim Miller6212cc02012-09-05 17:35:31 -0700929 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
930 removeCallback(null); // remove unused references
931 sendUpdates(callback);
932 }
933
934 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
935 // Notify listener of the current state
936 callback.onRefreshBatteryInfo(mBatteryStatus);
937 callback.onTimeChanged();
938 callback.onRingerModeChanged(mRingMode);
939 callback.onPhoneStateChanged(mPhoneState);
940 callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
941 callback.onClockVisibilityChanged();
942 callback.onSimStateChanged(mSimState);
Jim Miller8f09fd22013-03-14 19:04:28 -0700943 callback.onMusicClientIdChanged(
944 mDisplayClientState.clientGeneration,
945 mDisplayClientState.clearing,
946 mDisplayClientState.intent);
947 callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState,
948 mDisplayClientState.playbackEventTime);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800949 }
950
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400951 public void sendKeyguardVisibilityChanged(boolean showing) {
952 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
953 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
954 message.arg1 = showing ? 1 : 0;
955 message.sendToTarget();
956 }
957
Jeff Sharkey054340d2011-09-01 22:28:03 -0700958 public void reportClockVisible(boolean visible) {
959 mClockVisible = visible;
960 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
961 }
962
Wink Savillea639b312012-07-10 12:37:54 -0700963 public IccCardConstants.State getSimState() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800964 return mSimState;
965 }
966
967 /**
Jim Miller90d5d462011-11-17 16:57:01 -0800968 * 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 -0800969 * have the information earlier than waiting for the intent
970 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -0800971 *
972 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
973 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800974 */
John Wang0f7b3f82011-05-31 11:20:55 -0700975 public void reportSimUnlocked() {
Wink Savillea639b312012-07-10 12:37:54 -0700976 handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800977 }
978
Brian Colonna7fce3802013-09-17 15:51:32 -0400979 /**
980 * Report that the emergency call button has been pressed and the emergency dialer is
981 * about to be displayed.
982 *
983 * @param bypassHandler runs immediately.
984 *
985 * NOTE: Must be called from UI thread if bypassHandler == true.
986 */
987 public void reportEmergencyCallAction(boolean bypassHandler) {
988 if (!bypassHandler) {
989 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
990 } else {
991 handleReportEmergencyCallAction();
992 }
993 }
994
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800995 public CharSequence getTelephonyPlmn() {
996 return mTelephonyPlmn;
997 }
998
999 public CharSequence getTelephonySpn() {
1000 return mTelephonySpn;
1001 }
1002
1003 /**
1004 * @return Whether the device is provisioned (whether they have gone through
1005 * the setup wizard)
1006 */
1007 public boolean isDeviceProvisioned() {
1008 return mDeviceProvisioned;
1009 }
1010
Jim Miller258341c2012-08-30 16:50:10 -07001011 public int getFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001012 return mFailedAttempts;
1013 }
1014
Jim Miller258341c2012-08-30 16:50:10 -07001015 public void clearFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001016 mFailedAttempts = 0;
Brian Colonnaea8441e2012-04-25 17:51:49 -04001017 mFailedBiometricUnlockAttempts = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001018 }
1019
Jim Miller258341c2012-08-30 16:50:10 -07001020 public void reportFailedUnlockAttempt() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001021 mFailedAttempts++;
1022 }
Jim Miller1c188282011-08-08 22:27:58 -07001023
Jeff Sharkey054340d2011-09-01 22:28:03 -07001024 public boolean isClockVisible() {
1025 return mClockVisible;
1026 }
1027
Brian Colonna267cb2b2011-09-26 13:52:25 -04001028 public int getPhoneState() {
1029 return mPhoneState;
1030 }
Steven Rossb9430d22011-11-23 07:54:09 -05001031
Brian Colonnaea8441e2012-04-25 17:51:49 -04001032 public void reportFailedBiometricUnlockAttempt() {
1033 mFailedBiometricUnlockAttempts++;
Steven Rossb9430d22011-11-23 07:54:09 -05001034 }
1035
Brian Colonnaea8441e2012-04-25 17:51:49 -04001036 public boolean getMaxBiometricUnlockAttemptsReached() {
1037 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
Steven Rossb9430d22011-11-23 07:54:09 -05001038 }
Jim Millerb0304762012-03-13 20:01:25 -07001039
Jim Miller0ff7f012012-10-11 20:40:01 -07001040 public boolean isAlternateUnlockEnabled() {
1041 return mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001042 }
1043
Jim Miller0ff7f012012-10-11 20:40:01 -07001044 public void setAlternateUnlockEnabled(boolean enabled) {
1045 mAlternateUnlockEnabled = enabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001046 }
1047
Jim Millerb0304762012-03-13 20:01:25 -07001048 public boolean isSimLocked() {
Jim Millerdcb3d842012-08-23 19:18:12 -07001049 return isSimLocked(mSimState);
1050 }
1051
1052 public static boolean isSimLocked(IccCardConstants.State state) {
1053 return state == IccCardConstants.State.PIN_REQUIRED
1054 || state == IccCardConstants.State.PUK_REQUIRED
1055 || state == IccCardConstants.State.PERM_DISABLED;
1056 }
1057
1058 public boolean isSimPinSecure() {
1059 return isSimPinSecure(mSimState);
1060 }
1061
1062 public static boolean isSimPinSecure(IccCardConstants.State state) {
1063 final IccCardConstants.State simState = state;
1064 return (simState == IccCardConstants.State.PIN_REQUIRED
1065 || simState == IccCardConstants.State.PUK_REQUIRED
1066 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001067 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001068
1069 public DisplayClientState getCachedDisplayClientState() {
1070 return mDisplayClientState;
1071 }
Jim Miller20daffd2013-10-07 14:59:53 -07001072
1073 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1074 // (KeyguardViewMediator, KeyguardHostView)
1075 public void dispatchScreenTurnedOn() {
1076 synchronized (this) {
1077 mScreenOn = true;
1078 }
1079 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1080 }
1081
1082 public void dispatchScreenTurndOff(int why) {
1083 synchronized(this) {
1084 mScreenOn = false;
1085 }
1086 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1087 }
1088
1089 public boolean isScreenOn() {
1090 return mScreenOn;
1091 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001092}