blob: dcec6541ce5d3ce73fc5e92a4cba40a49cf4fcff [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;
Adam Cohenefb3ffb2012-11-06 16:55:32 -080094
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080095
Jim Millerdcb3d842012-08-23 19:18:12 -070096 private static KeyguardUpdateMonitor sInstance;
97
Jim Millerbbf1a742012-07-17 18:30:30 -070098 private final Context mContext;
99
100 // Telephony state
101 private IccCardConstants.State mSimState = IccCardConstants.State.READY;
102 private CharSequence mTelephonyPlmn;
103 private CharSequence mTelephonySpn;
104 private int mRingMode;
105 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400106 private boolean mKeyguardIsVisible;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800107 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700108
Jim Millerdcb3d842012-08-23 19:18:12 -0700109 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700110 private boolean mDeviceProvisioned;
111
Jim Millerdcb3d842012-08-23 19:18:12 -0700112 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700113 private BatteryStatus mBatteryStatus;
114
Jim Millerdcb3d842012-08-23 19:18:12 -0700115 // Password attempts
Jim Millerbbf1a742012-07-17 18:30:30 -0700116 private int mFailedAttempts = 0;
117 private int mFailedBiometricUnlockAttempts = 0;
118
Jim Miller0ff7f012012-10-11 20:40:01 -0700119 private boolean mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400120
Jim Millerbbf1a742012-07-17 18:30:30 -0700121 private boolean mClockVisible;
122
Jim Miller6212cc02012-09-05 17:35:31 -0700123 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700124 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800125 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700126
Brian Colonnaa5239892013-04-15 11:45:40 -0400127 private boolean mSwitchingUser;
128
Jim Millerbbf1a742012-07-17 18:30:30 -0700129 private final Handler mHandler = new Handler() {
130 @Override
131 public void handleMessage(Message msg) {
132 switch (msg.what) {
133 case MSG_TIME_UPDATE:
134 handleTimeUpdate();
135 break;
136 case MSG_BATTERY_UPDATE:
137 handleBatteryUpdate((BatteryStatus) msg.obj);
138 break;
139 case MSG_CARRIER_INFO_UPDATE:
140 handleCarrierInfoUpdate();
141 break;
142 case MSG_SIM_STATE_CHANGE:
143 handleSimStateChange((SimArgs) msg.obj);
144 break;
145 case MSG_RINGER_MODE_CHANGED:
146 handleRingerModeChange(msg.arg1);
147 break;
148 case MSG_PHONE_STATE_CHANGED:
149 handlePhoneStateChanged((String)msg.obj);
150 break;
151 case MSG_CLOCK_VISIBILITY_CHANGED:
152 handleClockVisibilityChanged();
153 break;
154 case MSG_DEVICE_PROVISIONED:
155 handleDeviceProvisioned();
156 break;
157 case MSG_DPM_STATE_CHANGED:
158 handleDevicePolicyManagerStateChanged();
159 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500160 case MSG_USER_SWITCHING:
161 handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
162 break;
163 case MSG_USER_SWITCH_COMPLETE:
164 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700165 break;
166 case MSG_USER_REMOVED:
167 handleUserRemoved(msg.arg1);
168 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400169 case MSG_KEYGUARD_VISIBILITY_CHANGED:
170 handleKeyguardVisibilityChanged(msg.arg1);
171 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800172 case MSG_BOOT_COMPLETED:
173 handleBootCompleted();
174 break;
Jim Miller8f09fd22013-03-14 19:04:28 -0700175 case MSG_SET_CURRENT_CLIENT_ID:
176 handleSetGenerationId(msg.arg1, msg.arg2 != 0, (PendingIntent) msg.obj);
177 break;
178 case MSG_SET_PLAYBACK_STATE:
179 handleSetPlaybackState(msg.arg1, msg.arg2, (Long) msg.obj);
180 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700181 case MSG_USER_INFO_CHANGED:
182 handleUserInfoChanged(msg.arg1);
183 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700184 }
185 }
186 };
187
Jim Miller8f09fd22013-03-14 19:04:28 -0700188 private AudioManager mAudioManager;
189
190 static class DisplayClientState {
191 public int clientGeneration;
192 public boolean clearing;
193 public PendingIntent intent;
194 public int playbackState;
195 public long playbackEventTime;
196 }
197
198 private DisplayClientState mDisplayClientState = new DisplayClientState();
199
200 /**
201 * This currently implements the bare minimum required to enable showing and hiding
202 * KeyguardTransportControl. There's a lot of client state to maintain which is why
203 * KeyguardTransportControl maintains an independent connection while it's showing.
204 */
205 private final IRemoteControlDisplay.Stub mRemoteControlDisplay =
206 new IRemoteControlDisplay.Stub() {
207
Jean-Michel Trivibc43b4c2013-03-22 09:30:50 -0700208 public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
209 long currentPosMs, float speed) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700210 Message msg = mHandler.obtainMessage(MSG_SET_PLAYBACK_STATE,
211 generationId, state, stateChangeTimeMs);
212 mHandler.sendMessage(msg);
213 }
214
215 public void setMetadata(int generationId, Bundle metadata) {
216
217 }
218
Jean-Michel Trivi3261b532013-04-01 14:59:39 -0700219 public void setTransportControlInfo(int generationId, int flags, int posCapabilities) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700220
221 }
222
223 public void setArtwork(int generationId, Bitmap bitmap) {
224
225 }
226
227 public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
228
229 }
230
231 public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
232 boolean clearing) throws RemoteException {
233 Message msg = mHandler.obtainMessage(MSG_SET_CURRENT_CLIENT_ID,
234 clientGeneration, (clearing ? 1 : 0), mediaIntent);
235 mHandler.sendMessage(msg);
236 }
237 };
238
Jim Millerbbf1a742012-07-17 18:30:30 -0700239 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
240
241 public void onReceive(Context context, Intent intent) {
242 final String action = intent.getAction();
243 if (DEBUG) Log.d(TAG, "received broadcast " + action);
244
245 if (Intent.ACTION_TIME_TICK.equals(action)
246 || Intent.ACTION_TIME_CHANGED.equals(action)
247 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
248 mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
249 } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
250 mTelephonyPlmn = getTelephonyPlmnFrom(intent);
251 mTelephonySpn = getTelephonySpnFrom(intent);
252 mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
253 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
254 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
255 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
256 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
257 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
258 final Message msg = mHandler.obtainMessage(
259 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
260 mHandler.sendMessage(msg);
261 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
262 if (DEBUG_SIM_STATES) {
263 Log.v(TAG, "action " + action + " state" +
264 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
265 }
266 mHandler.sendMessage(mHandler.obtainMessage(
267 MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
268 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
269 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
270 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
271 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
272 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
273 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
274 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
275 .equals(action)) {
276 mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
Jim Millerbbf1a742012-07-17 18:30:30 -0700277 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
278 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
Jim Millerdcb3d842012-08-23 19:18:12 -0700279 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800280 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
281 mHandler.sendMessage(mHandler.obtainMessage(MSG_BOOT_COMPLETED));
Jim Millerbbf1a742012-07-17 18:30:30 -0700282 }
283 }
284 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700285
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700286 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
287
288 public void onReceive(Context context, Intent intent) {
289 final String action = intent.getAction();
290 if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
291 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
292 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
293 }
294 }
295 };
296
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800297 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800298 * When we receive a
299 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700300 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800301 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800302 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800303 */
304 private static class SimArgs {
Wink Savillea639b312012-07-10 12:37:54 -0700305 public final IccCardConstants.State simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800306
Wink Savillea639b312012-07-10 12:37:54 -0700307 SimArgs(IccCardConstants.State state) {
Jim Miller90d5d462011-11-17 16:57:01 -0800308 simState = state;
309 }
310
311 static SimArgs fromIntent(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700312 IccCardConstants.State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800313 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
314 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
315 }
Wink Savillea639b312012-07-10 12:37:54 -0700316 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
317 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700318 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700319 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700320
Wink Savillea639b312012-07-10 12:37:54 -0700321 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700322 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700323 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700324 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700325 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700326 }
Wink Savillea639b312012-07-10 12:37:54 -0700327 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
328 state = IccCardConstants.State.READY;
329 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800330 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700331 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
332 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
333 state = IccCardConstants.State.PIN_REQUIRED;
334 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
335 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800336 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700337 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800338 }
Wink Savillea639b312012-07-10 12:37:54 -0700339 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
340 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700341 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
342 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
343 // This is required because telephony doesn't return to "READY" after
344 // these state transitions. See bug 7197471.
345 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800346 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700347 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800348 }
Jim Miller90d5d462011-11-17 16:57:01 -0800349 return new SimArgs(state);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800350 }
351
352 public String toString() {
353 return simState.toString();
354 }
355 }
356
Jim Millerbbf1a742012-07-17 18:30:30 -0700357 /* package */ static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700358 public final int status;
359 public final int level;
360 public final int plugged;
361 public final int health;
362 public BatteryStatus(int status, int level, int plugged, int health) {
363 this.status = status;
364 this.level = level;
365 this.plugged = plugged;
366 this.health = health;
367 }
368
Jim Millerbbf1a742012-07-17 18:30:30 -0700369 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700370 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700371 * @return true if the device is plugged in.
372 */
373 boolean isPluggedIn() {
374 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700375 || plugged == BatteryManager.BATTERY_PLUGGED_USB
376 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700377 }
378
379 /**
380 * Whether or not the device is charged. Note that some devices never return 100% for
381 * battery level, so this allows either battery level or status to determine if the
382 * battery is charged.
383 * @return true if the device is charged
384 */
385 public boolean isCharged() {
386 return status == BATTERY_STATUS_FULL || level >= 100;
387 }
388
389 /**
390 * Whether battery is low and needs to be charged.
391 * @return true if battery is low
392 */
393 public boolean isBatteryLow() {
394 return level < LOW_BATTERY_THRESHOLD;
395 }
396
Jim Miller16464b82011-10-20 21:10:13 -0700397 }
398
Jim Millerdcb3d842012-08-23 19:18:12 -0700399 public static KeyguardUpdateMonitor getInstance(Context context) {
400 if (sInstance == null) {
401 sInstance = new KeyguardUpdateMonitor(context);
402 }
403 return sInstance;
404 }
405
Jim Miller8f09fd22013-03-14 19:04:28 -0700406 protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) {
407 mDisplayClientState.clientGeneration = clientGeneration;
408 mDisplayClientState.clearing = clearing;
409 mDisplayClientState.intent = p;
Jim Miller4894a012013-04-03 15:23:55 -0700410 if (DEBUG)
411 Log.v(TAG, "handleSetGenerationId(g=" + clientGeneration + ", clear=" + clearing + ")");
Jim Miller8f09fd22013-03-14 19:04:28 -0700412 for (int i = 0; i < mCallbacks.size(); i++) {
413 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
414 if (cb != null) {
415 cb.onMusicClientIdChanged(clientGeneration, clearing, p);
416 }
417 }
418 }
419
420 protected void handleSetPlaybackState(int generationId, int playbackState, long eventTime) {
Jim Miller4894a012013-04-03 15:23:55 -0700421 if (DEBUG)
422 Log.v(TAG, "handleSetPlaybackState(gen=" + generationId
423 + ", state=" + playbackState + ", t=" + eventTime + ")");
424 mDisplayClientState.playbackState = playbackState;
425 mDisplayClientState.playbackEventTime = eventTime;
Jim Miller8f09fd22013-03-14 19:04:28 -0700426 if (generationId == mDisplayClientState.clientGeneration) {
427 for (int i = 0; i < mCallbacks.size(); i++) {
428 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
429 if (cb != null) {
430 cb.onMusicPlaybackStateChanged(playbackState, eventTime);
431 }
432 }
433 } else {
434 Log.w(TAG, "Ignoring generation id " + generationId + " because it's not current");
435 }
436 }
437
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700438 private void handleUserInfoChanged(int userId) {
439 for (int i = 0; i < mCallbacks.size(); i++) {
440 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
441 if (cb != null) {
442 cb.onUserInfoChanged(userId);
443 }
444 }
445 }
446
Jim Millerdcb3d842012-08-23 19:18:12 -0700447 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800448 mContext = context;
Jim Miller47088bb2009-11-24 00:40:16 -0800449
Michael Jurkafff56142012-11-28 16:51:00 -0800450 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800451 // Since device can't be un-provisioned, we only need to register a content observer
452 // to update mDeviceProvisioned when we are...
453 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700454 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800455 }
Jim Miller47088bb2009-11-24 00:40:16 -0800456
Jim Millerbbf1a742012-07-17 18:30:30 -0700457 // Take a guess at initial SIM state, battery status and PLMN until we get an update
458 mSimState = IccCardConstants.State.NOT_READY;
Jim Miller16464b82011-10-20 21:10:13 -0700459 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800460 mTelephonyPlmn = getDefaultPlmn();
461
Jim Millerbbf1a742012-07-17 18:30:30 -0700462 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800463 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800464 filter.addAction(Intent.ACTION_TIME_TICK);
465 filter.addAction(Intent.ACTION_TIME_CHANGED);
466 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
467 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
468 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800469 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Wink Savillea639b312012-07-10 12:37:54 -0700470 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Jim Miller47088bb2009-11-24 00:40:16 -0800471 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerb0304762012-03-13 20:01:25 -0700472 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700473 filter.addAction(Intent.ACTION_USER_REMOVED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700474 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700475
Adam Cohenc276e822012-11-08 13:01:08 -0800476 final IntentFilter bootCompleteFilter = new IntentFilter();
477 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
478 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
479 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
480
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700481 final IntentFilter userInfoFilter = new IntentFilter(Intent.ACTION_USER_INFO_CHANGED);
482 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, userInfoFilter,
483 null, null);
484
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700485 try {
486 ActivityManagerNative.getDefault().registerUserSwitchObserver(
487 new IUserSwitchObserver.Stub() {
488 @Override
489 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500490 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700491 newUserId, 0, reply));
Brian Colonnaa5239892013-04-15 11:45:40 -0400492 mSwitchingUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700493 }
494 @Override
495 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500496 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
497 newUserId));
Brian Colonnaa5239892013-04-15 11:45:40 -0400498 mSwitchingUser = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700499 }
500 });
501 } catch (RemoteException e) {
502 // TODO Auto-generated catch block
503 e.printStackTrace();
504 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700505 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800506
Michael Jurkafff56142012-11-28 16:51:00 -0800507 private boolean isDeviceProvisionedInSettingsDb() {
508 return Settings.Global.getInt(mContext.getContentResolver(),
509 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
510 }
511
Jim Millerbbf1a742012-07-17 18:30:30 -0700512 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800513 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700514 @Override
515 public void onChange(boolean selfChange) {
516 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800517 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700518 if (mDeviceProvisioned) {
519 mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800520 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700521 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800522 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700523 };
524
525 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700526 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800527 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700528
529 // prevent a race condition between where we check the flag and where we register the
530 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800531 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700532 if (provisioned != mDeviceProvisioned) {
533 mDeviceProvisioned = provisioned;
534 if (mDeviceProvisioned) {
535 mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
536 }
537 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800538 }
539
Jim Millerbbf1a742012-07-17 18:30:30 -0700540 /**
541 * Handle {@link #MSG_DPM_STATE_CHANGED}
542 */
Jim Millerb0304762012-03-13 20:01:25 -0700543 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700544 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
545 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
546 if (cb != null) {
547 cb.onDevicePolicyManagerStateChanged();
548 }
Jim Millerb0304762012-03-13 20:01:25 -0700549 }
550 }
551
Jim Millerbbf1a742012-07-17 18:30:30 -0700552 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500553 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700554 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500555 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700556 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700557 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
558 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500559 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700560 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700561 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700562 try {
563 reply.sendResult(null);
564 } catch (RemoteException e) {
565 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700566 }
567
Jim Millerbbf1a742012-07-17 18:30:30 -0700568 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500569 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
570 */
571 protected void handleUserSwitchComplete(int userId) {
572 for (int i = 0; i < mCallbacks.size(); i++) {
573 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
574 if (cb != null) {
575 cb.onUserSwitchComplete(userId);
576 }
577 }
578 }
579
580 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800581 * Handle {@link #MSG_BOOT_COMPLETED}
582 */
583 protected void handleBootCompleted() {
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800584 mBootCompleted = true;
Jim Miller8f09fd22013-03-14 19:04:28 -0700585 mAudioManager = new AudioManager(mContext);
586 mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800587 for (int i = 0; i < mCallbacks.size(); i++) {
588 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
589 if (cb != null) {
590 cb.onBootCompleted();
591 }
592 }
593 }
594
595 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800596 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800597 * destroyed.
598 */
599 public boolean hasBootCompleted() {
600 return mBootCompleted;
601 }
602
603 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500604 * Handle {@link #MSG_USER_REMOVED}
Jim Millerbbf1a742012-07-17 18:30:30 -0700605 */
606 protected void handleUserRemoved(int userId) {
607 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) {
610 cb.onUserRemoved(userId);
611 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700612 }
613 }
614
615 /**
616 * Handle {@link #MSG_DEVICE_PROVISIONED}
617 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700618 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700619 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700620 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
621 if (cb != null) {
622 cb.onDeviceProvisioned();
623 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700624 }
Michael Jurkafff56142012-11-28 16:51:00 -0800625 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700626 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800627 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
628 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700629 }
630 }
631
Jim Millerbbf1a742012-07-17 18:30:30 -0700632 /**
633 * Handle {@link #MSG_PHONE_STATE_CHANGED}
634 */
Jim Millerc23024d2010-02-24 15:37:00 -0800635 protected void handlePhoneStateChanged(String newState) {
636 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700637 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
638 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
639 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
640 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
641 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
642 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
643 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700644 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700645 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
646 if (cb != null) {
647 cb.onPhoneStateChanged(mPhoneState);
648 }
Jim Millerc23024d2010-02-24 15:37:00 -0800649 }
650 }
651
Jim Millerbbf1a742012-07-17 18:30:30 -0700652 /**
653 * Handle {@link #MSG_RINGER_MODE_CHANGED}
654 */
Jim Miller47088bb2009-11-24 00:40:16 -0800655 protected void handleRingerModeChange(int mode) {
656 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700657 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700658 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700659 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
660 if (cb != null) {
661 cb.onRingerModeChanged(mode);
662 }
Jim Miller47088bb2009-11-24 00:40:16 -0800663 }
664 }
665
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800666 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800667 * Handle {@link #MSG_TIME_UPDATE}
668 */
669 private void handleTimeUpdate() {
670 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700671 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700672 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
673 if (cb != null) {
674 cb.onTimeChanged();
675 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800676 }
677 }
678
679 /**
680 * Handle {@link #MSG_BATTERY_UPDATE}
681 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700682 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800683 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700684 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
685 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700686 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700687 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700688 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
689 if (cb != null) {
690 cb.onRefreshBatteryInfo(status);
691 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800692 }
693 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800694 }
695
696 /**
697 * Handle {@link #MSG_CARRIER_INFO_UPDATE}
698 */
699 private void handleCarrierInfoUpdate() {
700 if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
701 + ", spn = " + mTelephonySpn);
702
Jim Millerbbf1a742012-07-17 18:30:30 -0700703 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700704 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
705 if (cb != null) {
706 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
707 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800708 }
709 }
710
711 /**
712 * Handle {@link #MSG_SIM_STATE_CHANGE}
713 */
714 private void handleSimStateChange(SimArgs simArgs) {
Wink Savillea639b312012-07-10 12:37:54 -0700715 final IccCardConstants.State state = simArgs.simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800716
717 if (DEBUG) {
718 Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
719 + "state resolved to " + state.toString());
720 }
721
Wink Savillea639b312012-07-10 12:37:54 -0700722 if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800723 mSimState = state;
Jim Millerbbf1a742012-07-17 18:30:30 -0700724 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700725 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
726 if (cb != null) {
727 cb.onSimStateChanged(state);
728 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800729 }
730 }
731 }
732
Jim Millerbbf1a742012-07-17 18:30:30 -0700733 /**
734 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
735 */
Jeff Sharkey054340d2011-09-01 22:28:03 -0700736 private void handleClockVisibilityChanged() {
737 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
Jim Millerbbf1a742012-07-17 18:30:30 -0700738 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700739 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
740 if (cb != null) {
741 cb.onClockVisibilityChanged();
742 }
Jeff Sharkey054340d2011-09-01 22:28:03 -0700743 }
744 }
745
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400746 /**
747 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
748 */
749 private void handleKeyguardVisibilityChanged(int showing) {
750 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -0400751 boolean isShowing = (showing == 1);
752 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400753 for (int i = 0; i < mCallbacks.size(); i++) {
754 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
755 if (cb != null) {
Danielle Millett5d2404d2012-11-01 00:05:27 -0400756 cb.onKeyguardVisibilityChanged(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400757 }
758 }
759 }
760
Danielle Millett5d2404d2012-11-01 00:05:27 -0400761 public boolean isKeyguardVisible() {
762 return mKeyguardIsVisible;
763 }
764
Brian Colonnaa5239892013-04-15 11:45:40 -0400765 public boolean isSwitchingUser() {
766 return mSwitchingUser;
767 }
768
Jim Miller16464b82011-10-20 21:10:13 -0700769 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700770 final boolean nowPluggedIn = current.isPluggedIn();
771 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -0800772 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -0700773 wasPluggedIn == true && nowPluggedIn == true
774 && (old.status != current.status);
775
776 // change in plug state is always interesting
777 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800778 return true;
779 }
780
781 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -0700782 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800783 return true;
784 }
785
Jim Miller16464b82011-10-20 21:10:13 -0700786 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -0700787 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -0700788 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800789 }
790 return false;
791 }
792
793 /**
Wink Savillea639b312012-07-10 12:37:54 -0700794 * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800795 * @return The string to use for the plmn, or null if it should not be shown.
796 */
797 private CharSequence getTelephonyPlmnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700798 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
799 final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
Jim Millerbbf1a742012-07-17 18:30:30 -0700800 return (plmn != null) ? plmn : getDefaultPlmn();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800801 }
802 return null;
803 }
804
805 /**
806 * @return The default plmn (no service)
807 */
808 private CharSequence getDefaultPlmn() {
Jim Miller5ecd8112013-01-09 18:50:26 -0800809 return mContext.getResources().getText(R.string.keyguard_carrier_default);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800810 }
811
812 /**
813 * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
814 * @return The string to use for the plmn, or null if it should not be shown.
815 */
816 private CharSequence getTelephonySpnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700817 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
818 final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800819 if (spn != null) {
820 return spn;
821 }
822 }
823 return null;
824 }
825
826 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700827 * Remove the given observer's callback.
828 *
Jim Miller6212cc02012-09-05 17:35:31 -0700829 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800830 */
Jim Miller6212cc02012-09-05 17:35:31 -0700831 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
832 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
833 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
834 if (mCallbacks.get(i).get() == callback) {
835 mCallbacks.remove(i);
836 }
837 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800838 }
839
840 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800841 * Register to receive notifications about general keyguard information
842 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -0700843 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800844 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700845 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -0700846 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
847 // Prevent adding duplicate callbacks
848 for (int i = 0; i < mCallbacks.size(); i++) {
849 if (mCallbacks.get(i).get() == callback) {
850 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
851 new Exception("Called by"));
852 return;
Jim Millerdcb3d842012-08-23 19:18:12 -0700853 }
854 }
Jim Miller6212cc02012-09-05 17:35:31 -0700855 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
856 removeCallback(null); // remove unused references
857 sendUpdates(callback);
858 }
859
860 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
861 // Notify listener of the current state
862 callback.onRefreshBatteryInfo(mBatteryStatus);
863 callback.onTimeChanged();
864 callback.onRingerModeChanged(mRingMode);
865 callback.onPhoneStateChanged(mPhoneState);
866 callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
867 callback.onClockVisibilityChanged();
868 callback.onSimStateChanged(mSimState);
Jim Miller8f09fd22013-03-14 19:04:28 -0700869 callback.onMusicClientIdChanged(
870 mDisplayClientState.clientGeneration,
871 mDisplayClientState.clearing,
872 mDisplayClientState.intent);
873 callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState,
874 mDisplayClientState.playbackEventTime);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800875 }
876
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400877 public void sendKeyguardVisibilityChanged(boolean showing) {
878 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
879 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
880 message.arg1 = showing ? 1 : 0;
881 message.sendToTarget();
882 }
883
Jeff Sharkey054340d2011-09-01 22:28:03 -0700884 public void reportClockVisible(boolean visible) {
885 mClockVisible = visible;
886 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
887 }
888
Wink Savillea639b312012-07-10 12:37:54 -0700889 public IccCardConstants.State getSimState() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800890 return mSimState;
891 }
892
893 /**
Jim Miller90d5d462011-11-17 16:57:01 -0800894 * 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 -0800895 * have the information earlier than waiting for the intent
896 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -0800897 *
898 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
899 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800900 */
John Wang0f7b3f82011-05-31 11:20:55 -0700901 public void reportSimUnlocked() {
Wink Savillea639b312012-07-10 12:37:54 -0700902 handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800903 }
904
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800905 public CharSequence getTelephonyPlmn() {
906 return mTelephonyPlmn;
907 }
908
909 public CharSequence getTelephonySpn() {
910 return mTelephonySpn;
911 }
912
913 /**
914 * @return Whether the device is provisioned (whether they have gone through
915 * the setup wizard)
916 */
917 public boolean isDeviceProvisioned() {
918 return mDeviceProvisioned;
919 }
920
Jim Miller258341c2012-08-30 16:50:10 -0700921 public int getFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800922 return mFailedAttempts;
923 }
924
Jim Miller258341c2012-08-30 16:50:10 -0700925 public void clearFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800926 mFailedAttempts = 0;
Brian Colonnaea8441e2012-04-25 17:51:49 -0400927 mFailedBiometricUnlockAttempts = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800928 }
929
Jim Miller258341c2012-08-30 16:50:10 -0700930 public void reportFailedUnlockAttempt() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800931 mFailedAttempts++;
932 }
Jim Miller1c188282011-08-08 22:27:58 -0700933
Jeff Sharkey054340d2011-09-01 22:28:03 -0700934 public boolean isClockVisible() {
935 return mClockVisible;
936 }
937
Brian Colonna267cb2b2011-09-26 13:52:25 -0400938 public int getPhoneState() {
939 return mPhoneState;
940 }
Steven Rossb9430d22011-11-23 07:54:09 -0500941
Brian Colonnaea8441e2012-04-25 17:51:49 -0400942 public void reportFailedBiometricUnlockAttempt() {
943 mFailedBiometricUnlockAttempts++;
Steven Rossb9430d22011-11-23 07:54:09 -0500944 }
945
Brian Colonnaea8441e2012-04-25 17:51:49 -0400946 public boolean getMaxBiometricUnlockAttemptsReached() {
947 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
Steven Rossb9430d22011-11-23 07:54:09 -0500948 }
Jim Millerb0304762012-03-13 20:01:25 -0700949
Jim Miller0ff7f012012-10-11 20:40:01 -0700950 public boolean isAlternateUnlockEnabled() {
951 return mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400952 }
953
Jim Miller0ff7f012012-10-11 20:40:01 -0700954 public void setAlternateUnlockEnabled(boolean enabled) {
955 mAlternateUnlockEnabled = enabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400956 }
957
Jim Millerb0304762012-03-13 20:01:25 -0700958 public boolean isSimLocked() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700959 return isSimLocked(mSimState);
960 }
961
962 public static boolean isSimLocked(IccCardConstants.State state) {
963 return state == IccCardConstants.State.PIN_REQUIRED
964 || state == IccCardConstants.State.PUK_REQUIRED
965 || state == IccCardConstants.State.PERM_DISABLED;
966 }
967
968 public boolean isSimPinSecure() {
969 return isSimPinSecure(mSimState);
970 }
971
972 public static boolean isSimPinSecure(IccCardConstants.State state) {
973 final IccCardConstants.State simState = state;
974 return (simState == IccCardConstants.State.PIN_REQUIRED
975 || simState == IccCardConstants.State.PUK_REQUIRED
976 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -0700977 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700978
979 public DisplayClientState getCachedDisplayClientState() {
980 return mDisplayClientState;
981 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800982}