blob: 734f51714be6744386a3a21d317b68e6c7214112 [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;
Adam Cohenefb3ffb2012-11-06 16:55:32 -080095
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096
Jim Millerdcb3d842012-08-23 19:18:12 -070097 private static KeyguardUpdateMonitor sInstance;
98
Jim Millerbbf1a742012-07-17 18:30:30 -070099 private final Context mContext;
100
101 // Telephony state
102 private IccCardConstants.State mSimState = IccCardConstants.State.READY;
103 private CharSequence mTelephonyPlmn;
104 private CharSequence mTelephonySpn;
105 private int mRingMode;
106 private int mPhoneState;
Danielle Millett5d2404d2012-11-01 00:05:27 -0400107 private boolean mKeyguardIsVisible;
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800108 private boolean mBootCompleted;
Jim Millerbbf1a742012-07-17 18:30:30 -0700109
Jim Millerdcb3d842012-08-23 19:18:12 -0700110 // Device provisioning state
Jim Millerbbf1a742012-07-17 18:30:30 -0700111 private boolean mDeviceProvisioned;
112
Jim Millerdcb3d842012-08-23 19:18:12 -0700113 // Battery status
Jim Millerbbf1a742012-07-17 18:30:30 -0700114 private BatteryStatus mBatteryStatus;
115
Jim Millerdcb3d842012-08-23 19:18:12 -0700116 // Password attempts
Jim Millerbbf1a742012-07-17 18:30:30 -0700117 private int mFailedAttempts = 0;
118 private int mFailedBiometricUnlockAttempts = 0;
119
Jim Miller0ff7f012012-10-11 20:40:01 -0700120 private boolean mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -0400121
Jim Millerbbf1a742012-07-17 18:30:30 -0700122 private boolean mClockVisible;
123
Jim Miller6212cc02012-09-05 17:35:31 -0700124 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
Jim Millerdcb3d842012-08-23 19:18:12 -0700125 mCallbacks = Lists.newArrayList();
Michael Jurkafff56142012-11-28 16:51:00 -0800126 private ContentObserver mDeviceProvisionedObserver;
Jim Millerbbf1a742012-07-17 18:30:30 -0700127
Brian Colonnaa5239892013-04-15 11:45:40 -0400128 private boolean mSwitchingUser;
129
Jim Millerbbf1a742012-07-17 18:30:30 -0700130 private final Handler mHandler = new Handler() {
131 @Override
132 public void handleMessage(Message msg) {
133 switch (msg.what) {
134 case MSG_TIME_UPDATE:
135 handleTimeUpdate();
136 break;
137 case MSG_BATTERY_UPDATE:
138 handleBatteryUpdate((BatteryStatus) msg.obj);
139 break;
140 case MSG_CARRIER_INFO_UPDATE:
141 handleCarrierInfoUpdate();
142 break;
143 case MSG_SIM_STATE_CHANGE:
144 handleSimStateChange((SimArgs) msg.obj);
145 break;
146 case MSG_RINGER_MODE_CHANGED:
147 handleRingerModeChange(msg.arg1);
148 break;
149 case MSG_PHONE_STATE_CHANGED:
150 handlePhoneStateChanged((String)msg.obj);
151 break;
152 case MSG_CLOCK_VISIBILITY_CHANGED:
153 handleClockVisibilityChanged();
154 break;
155 case MSG_DEVICE_PROVISIONED:
156 handleDeviceProvisioned();
157 break;
158 case MSG_DPM_STATE_CHANGED:
159 handleDevicePolicyManagerStateChanged();
160 break;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500161 case MSG_USER_SWITCHING:
162 handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
163 break;
164 case MSG_USER_SWITCH_COMPLETE:
165 handleUserSwitchComplete(msg.arg1);
Jim Millerbbf1a742012-07-17 18:30:30 -0700166 break;
167 case MSG_USER_REMOVED:
168 handleUserRemoved(msg.arg1);
169 break;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400170 case MSG_KEYGUARD_VISIBILITY_CHANGED:
171 handleKeyguardVisibilityChanged(msg.arg1);
172 break;
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800173 case MSG_BOOT_COMPLETED:
174 handleBootCompleted();
175 break;
Jim Miller8f09fd22013-03-14 19:04:28 -0700176 case MSG_SET_CURRENT_CLIENT_ID:
177 handleSetGenerationId(msg.arg1, msg.arg2 != 0, (PendingIntent) msg.obj);
178 break;
179 case MSG_SET_PLAYBACK_STATE:
180 handleSetPlaybackState(msg.arg1, msg.arg2, (Long) msg.obj);
181 break;
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700182 case MSG_USER_INFO_CHANGED:
183 handleUserInfoChanged(msg.arg1);
184 break;
Brian Colonna7fce3802013-09-17 15:51:32 -0400185 case MSG_REPORT_EMERGENCY_CALL_ACTION:
186 handleReportEmergencyCallAction();
187 break;
Jim Millerbbf1a742012-07-17 18:30:30 -0700188 }
189 }
190 };
191
Jim Miller8f09fd22013-03-14 19:04:28 -0700192 private AudioManager mAudioManager;
193
194 static class DisplayClientState {
195 public int clientGeneration;
196 public boolean clearing;
197 public PendingIntent intent;
198 public int playbackState;
199 public long playbackEventTime;
200 }
201
202 private DisplayClientState mDisplayClientState = new DisplayClientState();
203
204 /**
205 * This currently implements the bare minimum required to enable showing and hiding
206 * KeyguardTransportControl. There's a lot of client state to maintain which is why
207 * KeyguardTransportControl maintains an independent connection while it's showing.
208 */
209 private final IRemoteControlDisplay.Stub mRemoteControlDisplay =
210 new IRemoteControlDisplay.Stub() {
211
Jean-Michel Trivibc43b4c2013-03-22 09:30:50 -0700212 public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
213 long currentPosMs, float speed) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700214 Message msg = mHandler.obtainMessage(MSG_SET_PLAYBACK_STATE,
215 generationId, state, stateChangeTimeMs);
216 mHandler.sendMessage(msg);
217 }
218
219 public void setMetadata(int generationId, Bundle metadata) {
220
221 }
222
Jean-Michel Trivi3261b532013-04-01 14:59:39 -0700223 public void setTransportControlInfo(int generationId, int flags, int posCapabilities) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700224
225 }
226
227 public void setArtwork(int generationId, Bitmap bitmap) {
228
229 }
230
231 public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
232
233 }
234
235 public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
236 boolean clearing) throws RemoteException {
237 Message msg = mHandler.obtainMessage(MSG_SET_CURRENT_CLIENT_ID,
238 clientGeneration, (clearing ? 1 : 0), mediaIntent);
239 mHandler.sendMessage(msg);
240 }
241 };
242
Jim Millerbbf1a742012-07-17 18:30:30 -0700243 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
244
245 public void onReceive(Context context, Intent intent) {
246 final String action = intent.getAction();
247 if (DEBUG) Log.d(TAG, "received broadcast " + action);
248
249 if (Intent.ACTION_TIME_TICK.equals(action)
250 || Intent.ACTION_TIME_CHANGED.equals(action)
251 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700252 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700253 } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
254 mTelephonyPlmn = getTelephonyPlmnFrom(intent);
255 mTelephonySpn = getTelephonySpnFrom(intent);
Jim Miller90873d52013-09-26 18:11:38 -0700256 mHandler.sendEmptyMessage(MSG_CARRIER_INFO_UPDATE);
Jim Millerbbf1a742012-07-17 18:30:30 -0700257 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
258 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
259 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
260 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
261 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
262 final Message msg = mHandler.obtainMessage(
263 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
264 mHandler.sendMessage(msg);
265 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
266 if (DEBUG_SIM_STATES) {
267 Log.v(TAG, "action " + action + " state" +
268 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
269 }
270 mHandler.sendMessage(mHandler.obtainMessage(
271 MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
272 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
273 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
274 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
275 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
276 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
277 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
278 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
279 .equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700280 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700281 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
282 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
Jim Millerdcb3d842012-08-23 19:18:12 -0700283 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800284 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Jim Miller90873d52013-09-26 18:11:38 -0700285 dispatchBootCompleted();
Jim Millerbbf1a742012-07-17 18:30:30 -0700286 }
287 }
288 };
Jim Miller2de5ee82012-06-14 22:22:50 -0700289
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700290 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
291
292 public void onReceive(Context context, Intent intent) {
293 final String action = intent.getAction();
294 if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
295 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
296 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
297 }
298 }
299 };
300
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800301 /**
Jim Miller47088bb2009-11-24 00:40:16 -0800302 * When we receive a
303 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
Wink Saville37c124c2009-04-02 01:37:02 -0700304 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800305 * we need a single object to pass to the handler. This class helps decode
Jim Miller47088bb2009-11-24 00:40:16 -0800306 * the intent and provide a {@link SimCard.State} result.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800307 */
308 private static class SimArgs {
Wink Savillea639b312012-07-10 12:37:54 -0700309 public final IccCardConstants.State simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800310
Wink Savillea639b312012-07-10 12:37:54 -0700311 SimArgs(IccCardConstants.State state) {
Jim Miller90d5d462011-11-17 16:57:01 -0800312 simState = state;
313 }
314
315 static SimArgs fromIntent(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700316 IccCardConstants.State state;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800317 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
318 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
319 }
Wink Savillea639b312012-07-10 12:37:54 -0700320 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
321 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
John Wangb0b24b32011-06-10 17:23:51 -0700322 final String absentReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700323 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
John Wangb0b24b32011-06-10 17:23:51 -0700324
Wink Savillea639b312012-07-10 12:37:54 -0700325 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
John Wangb0b24b32011-06-10 17:23:51 -0700326 absentReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700327 state = IccCardConstants.State.PERM_DISABLED;
John Wangb0b24b32011-06-10 17:23:51 -0700328 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700329 state = IccCardConstants.State.ABSENT;
John Wangb0b24b32011-06-10 17:23:51 -0700330 }
Wink Savillea639b312012-07-10 12:37:54 -0700331 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
332 state = IccCardConstants.State.READY;
333 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800334 final String lockedReason = intent
Wink Savillea639b312012-07-10 12:37:54 -0700335 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
336 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
337 state = IccCardConstants.State.PIN_REQUIRED;
338 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
339 state = IccCardConstants.State.PUK_REQUIRED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800340 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700341 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800342 }
Wink Savillea639b312012-07-10 12:37:54 -0700343 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
344 state = IccCardConstants.State.NETWORK_LOCKED;
Jim Miller109f1fd2012-09-19 20:44:16 -0700345 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
346 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
347 // This is required because telephony doesn't return to "READY" after
348 // these state transitions. See bug 7197471.
349 state = IccCardConstants.State.READY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800350 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700351 state = IccCardConstants.State.UNKNOWN;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800352 }
Jim Miller90d5d462011-11-17 16:57:01 -0800353 return new SimArgs(state);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800354 }
355
356 public String toString() {
357 return simState.toString();
358 }
359 }
360
Jim Millerbbf1a742012-07-17 18:30:30 -0700361 /* package */ static class BatteryStatus {
Jim Miller16464b82011-10-20 21:10:13 -0700362 public final int status;
363 public final int level;
364 public final int plugged;
365 public final int health;
366 public BatteryStatus(int status, int level, int plugged, int health) {
367 this.status = status;
368 this.level = level;
369 this.plugged = plugged;
370 this.health = health;
371 }
372
Jim Millerbbf1a742012-07-17 18:30:30 -0700373 /**
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700374 * Determine whether the device is plugged in (USB, power, or wireless).
Jim Millerbbf1a742012-07-17 18:30:30 -0700375 * @return true if the device is plugged in.
376 */
377 boolean isPluggedIn() {
378 return plugged == BatteryManager.BATTERY_PLUGGED_AC
Brian Muramatsua92a01b2012-09-05 21:54:39 -0700379 || plugged == BatteryManager.BATTERY_PLUGGED_USB
380 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
Jim Millerbbf1a742012-07-17 18:30:30 -0700381 }
382
383 /**
384 * Whether or not the device is charged. Note that some devices never return 100% for
385 * battery level, so this allows either battery level or status to determine if the
386 * battery is charged.
387 * @return true if the device is charged
388 */
389 public boolean isCharged() {
390 return status == BATTERY_STATUS_FULL || level >= 100;
391 }
392
393 /**
394 * Whether battery is low and needs to be charged.
395 * @return true if battery is low
396 */
397 public boolean isBatteryLow() {
398 return level < LOW_BATTERY_THRESHOLD;
399 }
400
Jim Miller16464b82011-10-20 21:10:13 -0700401 }
402
Jim Millerdcb3d842012-08-23 19:18:12 -0700403 public static KeyguardUpdateMonitor getInstance(Context context) {
404 if (sInstance == null) {
405 sInstance = new KeyguardUpdateMonitor(context);
406 }
407 return sInstance;
408 }
409
Adam Powell43a372f2013-09-27 17:43:53 -0700410 /**
411 * IMPORTANT: Must be called from UI thread.
412 */
413 public void dispatchSetBackground(Bitmap bmp) {
414 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
415 final int count = mCallbacks.size();
416 for (int i = 0; i < count; i++) {
417 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
418 if (cb != null) {
419 cb.onSetBackground(bmp);
420 }
421 }
422 }
423
Jim Miller8f09fd22013-03-14 19:04:28 -0700424 protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) {
425 mDisplayClientState.clientGeneration = clientGeneration;
426 mDisplayClientState.clearing = clearing;
427 mDisplayClientState.intent = p;
Jim Miller4894a012013-04-03 15:23:55 -0700428 if (DEBUG)
429 Log.v(TAG, "handleSetGenerationId(g=" + clientGeneration + ", clear=" + clearing + ")");
Jim Miller8f09fd22013-03-14 19:04:28 -0700430 for (int i = 0; i < mCallbacks.size(); i++) {
431 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
432 if (cb != null) {
433 cb.onMusicClientIdChanged(clientGeneration, clearing, p);
434 }
435 }
436 }
437
438 protected void handleSetPlaybackState(int generationId, int playbackState, long eventTime) {
Jim Miller4894a012013-04-03 15:23:55 -0700439 if (DEBUG)
440 Log.v(TAG, "handleSetPlaybackState(gen=" + generationId
441 + ", state=" + playbackState + ", t=" + eventTime + ")");
442 mDisplayClientState.playbackState = playbackState;
443 mDisplayClientState.playbackEventTime = eventTime;
Jim Miller8f09fd22013-03-14 19:04:28 -0700444 if (generationId == mDisplayClientState.clientGeneration) {
445 for (int i = 0; i < mCallbacks.size(); i++) {
446 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
447 if (cb != null) {
448 cb.onMusicPlaybackStateChanged(playbackState, eventTime);
449 }
450 }
451 } else {
452 Log.w(TAG, "Ignoring generation id " + generationId + " because it's not current");
453 }
454 }
455
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700456 private void handleUserInfoChanged(int userId) {
457 for (int i = 0; i < mCallbacks.size(); i++) {
458 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
459 if (cb != null) {
460 cb.onUserInfoChanged(userId);
461 }
462 }
463 }
464
Jim Millerdcb3d842012-08-23 19:18:12 -0700465 private KeyguardUpdateMonitor(Context context) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800466 mContext = context;
Jim Miller47088bb2009-11-24 00:40:16 -0800467
Michael Jurkafff56142012-11-28 16:51:00 -0800468 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800469 // Since device can't be un-provisioned, we only need to register a content observer
470 // to update mDeviceProvisioned when we are...
471 if (!mDeviceProvisioned) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700472 watchForDeviceProvisioning();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800473 }
Jim Miller47088bb2009-11-24 00:40:16 -0800474
Jim Millerbbf1a742012-07-17 18:30:30 -0700475 // Take a guess at initial SIM state, battery status and PLMN until we get an update
476 mSimState = IccCardConstants.State.NOT_READY;
Jim Miller16464b82011-10-20 21:10:13 -0700477 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800478 mTelephonyPlmn = getDefaultPlmn();
479
Jim Millerbbf1a742012-07-17 18:30:30 -0700480 // Watch for interesting updates
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800481 final IntentFilter filter = new IntentFilter();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800482 filter.addAction(Intent.ACTION_TIME_TICK);
483 filter.addAction(Intent.ACTION_TIME_CHANGED);
484 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
485 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
486 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jim Millerc23024d2010-02-24 15:37:00 -0800487 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Wink Savillea639b312012-07-10 12:37:54 -0700488 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Jim Miller47088bb2009-11-24 00:40:16 -0800489 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
Jim Millerb0304762012-03-13 20:01:25 -0700490 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700491 filter.addAction(Intent.ACTION_USER_REMOVED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700492 context.registerReceiver(mBroadcastReceiver, filter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700493
Adam Cohenc276e822012-11-08 13:01:08 -0800494 final IntentFilter bootCompleteFilter = new IntentFilter();
495 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
496 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
497 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
498
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700499 final IntentFilter userInfoFilter = new IntentFilter(Intent.ACTION_USER_INFO_CHANGED);
500 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, userInfoFilter,
501 null, null);
502
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700503 try {
504 ActivityManagerNative.getDefault().registerUserSwitchObserver(
505 new IUserSwitchObserver.Stub() {
506 @Override
507 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500508 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700509 newUserId, 0, reply));
Brian Colonnaa5239892013-04-15 11:45:40 -0400510 mSwitchingUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700511 }
512 @Override
513 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500514 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
515 newUserId));
Brian Colonnaa5239892013-04-15 11:45:40 -0400516 mSwitchingUser = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700517 }
518 });
519 } catch (RemoteException e) {
520 // TODO Auto-generated catch block
521 e.printStackTrace();
522 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700523 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800524
Michael Jurkafff56142012-11-28 16:51:00 -0800525 private boolean isDeviceProvisionedInSettingsDb() {
526 return Settings.Global.getInt(mContext.getContentResolver(),
527 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
528 }
529
Jim Millerbbf1a742012-07-17 18:30:30 -0700530 private void watchForDeviceProvisioning() {
Michael Jurkafff56142012-11-28 16:51:00 -0800531 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700532 @Override
533 public void onChange(boolean selfChange) {
534 super.onChange(selfChange);
Michael Jurkafff56142012-11-28 16:51:00 -0800535 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700536 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700537 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800538 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700539 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800540 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700541 };
542
543 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700544 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
Michael Jurkafff56142012-11-28 16:51:00 -0800545 false, mDeviceProvisionedObserver);
Jim Millerbbf1a742012-07-17 18:30:30 -0700546
547 // prevent a race condition between where we check the flag and where we register the
548 // observer by grabbing the value once again...
Michael Jurkafff56142012-11-28 16:51:00 -0800549 boolean provisioned = isDeviceProvisionedInSettingsDb();
Jim Millerbbf1a742012-07-17 18:30:30 -0700550 if (provisioned != mDeviceProvisioned) {
551 mDeviceProvisioned = provisioned;
552 if (mDeviceProvisioned) {
Jim Miller90873d52013-09-26 18:11:38 -0700553 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
Jim Millerbbf1a742012-07-17 18:30:30 -0700554 }
555 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800556 }
557
Jim Millerbbf1a742012-07-17 18:30:30 -0700558 /**
559 * Handle {@link #MSG_DPM_STATE_CHANGED}
560 */
Jim Millerb0304762012-03-13 20:01:25 -0700561 protected void handleDevicePolicyManagerStateChanged() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700562 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
563 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
564 if (cb != null) {
565 cb.onDevicePolicyManagerStateChanged();
566 }
Jim Millerb0304762012-03-13 20:01:25 -0700567 }
568 }
569
Jim Millerbbf1a742012-07-17 18:30:30 -0700570 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500571 * Handle {@link #MSG_USER_SWITCHING}
Jim Millerbbf1a742012-07-17 18:30:30 -0700572 */
Chris Wrenf41c61b2012-11-29 15:19:54 -0500573 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700574 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700575 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
576 if (cb != null) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500577 cb.onUserSwitching(userId);
Jim Millerdcb3d842012-08-23 19:18:12 -0700578 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700579 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700580 try {
581 reply.sendResult(null);
582 } catch (RemoteException e) {
583 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700584 }
585
Jim Millerbbf1a742012-07-17 18:30:30 -0700586 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500587 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
588 */
589 protected void handleUserSwitchComplete(int userId) {
590 for (int i = 0; i < mCallbacks.size(); i++) {
591 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
592 if (cb != null) {
593 cb.onUserSwitchComplete(userId);
594 }
595 }
596 }
597
598 /**
Jim Miller90873d52013-09-26 18:11:38 -0700599 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
600 * keyguard crashes sometime after boot, then it will never receive this
601 * broadcast and hence not handle the event. This method is ultimately called by
602 * PhoneWindowManager in this case.
603 */
604 protected void dispatchBootCompleted() {
605 if (!mBootCompleted) {
606 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
607 }
608 }
609
610 /**
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800611 * Handle {@link #MSG_BOOT_COMPLETED}
612 */
613 protected void handleBootCompleted() {
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800614 mBootCompleted = true;
Jim Miller8f09fd22013-03-14 19:04:28 -0700615 mAudioManager = new AudioManager(mContext);
616 mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800617 for (int i = 0; i < mCallbacks.size(); i++) {
618 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
619 if (cb != null) {
620 cb.onBootCompleted();
621 }
622 }
623 }
624
625 /**
Jim Miller5ecd8112013-01-09 18:50:26 -0800626 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
Adam Cohen4eb36cf2012-11-07 11:45:30 -0800627 * destroyed.
628 */
629 public boolean hasBootCompleted() {
630 return mBootCompleted;
631 }
632
633 /**
Chris Wrenf41c61b2012-11-29 15:19:54 -0500634 * Handle {@link #MSG_USER_REMOVED}
Jim Millerbbf1a742012-07-17 18:30:30 -0700635 */
636 protected void handleUserRemoved(int userId) {
637 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700638 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
639 if (cb != null) {
640 cb.onUserRemoved(userId);
641 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700642 }
643 }
644
645 /**
646 * Handle {@link #MSG_DEVICE_PROVISIONED}
647 */
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700648 protected void handleDeviceProvisioned() {
Jim Millerbbf1a742012-07-17 18:30:30 -0700649 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700650 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
651 if (cb != null) {
652 cb.onDeviceProvisioned();
653 }
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700654 }
Michael Jurkafff56142012-11-28 16:51:00 -0800655 if (mDeviceProvisionedObserver != null) {
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700656 // We don't need the observer anymore...
Michael Jurkafff56142012-11-28 16:51:00 -0800657 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
658 mDeviceProvisionedObserver = null;
Nick Pelly24d7b5f2011-10-11 12:51:09 -0700659 }
660 }
661
Jim Millerbbf1a742012-07-17 18:30:30 -0700662 /**
663 * Handle {@link #MSG_PHONE_STATE_CHANGED}
664 */
Jim Millerc23024d2010-02-24 15:37:00 -0800665 protected void handlePhoneStateChanged(String newState) {
666 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700667 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
668 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
669 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
670 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
671 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
672 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
673 }
Jim Millerbbf1a742012-07-17 18:30:30 -0700674 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700675 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
676 if (cb != null) {
677 cb.onPhoneStateChanged(mPhoneState);
678 }
Jim Millerc23024d2010-02-24 15:37:00 -0800679 }
680 }
681
Jim Millerbbf1a742012-07-17 18:30:30 -0700682 /**
683 * Handle {@link #MSG_RINGER_MODE_CHANGED}
684 */
Jim Miller47088bb2009-11-24 00:40:16 -0800685 protected void handleRingerModeChange(int mode) {
686 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
Jim Miller3f5f83b2011-09-26 15:17:05 -0700687 mRingMode = mode;
Jim Millerbbf1a742012-07-17 18:30:30 -0700688 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700689 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
690 if (cb != null) {
691 cb.onRingerModeChanged(mode);
692 }
Jim Miller47088bb2009-11-24 00:40:16 -0800693 }
694 }
695
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800696 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800697 * Handle {@link #MSG_TIME_UPDATE}
698 */
699 private void handleTimeUpdate() {
700 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700701 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700702 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
703 if (cb != null) {
704 cb.onTimeChanged();
705 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800706 }
707 }
708
709 /**
710 * Handle {@link #MSG_BATTERY_UPDATE}
711 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700712 private void handleBatteryUpdate(BatteryStatus status) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800713 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
Jim Millerbbf1a742012-07-17 18:30:30 -0700714 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
715 mBatteryStatus = status;
Jim Miller16464b82011-10-20 21:10:13 -0700716 if (batteryUpdateInteresting) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700717 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700718 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
719 if (cb != null) {
720 cb.onRefreshBatteryInfo(status);
721 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800722 }
723 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800724 }
725
726 /**
727 * Handle {@link #MSG_CARRIER_INFO_UPDATE}
728 */
729 private void handleCarrierInfoUpdate() {
730 if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
731 + ", spn = " + mTelephonySpn);
732
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.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
737 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800738 }
739 }
740
741 /**
742 * Handle {@link #MSG_SIM_STATE_CHANGE}
743 */
744 private void handleSimStateChange(SimArgs simArgs) {
Wink Savillea639b312012-07-10 12:37:54 -0700745 final IccCardConstants.State state = simArgs.simState;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800746
747 if (DEBUG) {
748 Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
749 + "state resolved to " + state.toString());
750 }
751
Wink Savillea639b312012-07-10 12:37:54 -0700752 if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800753 mSimState = state;
Jim Millerbbf1a742012-07-17 18:30:30 -0700754 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700755 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
756 if (cb != null) {
757 cb.onSimStateChanged(state);
758 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800759 }
760 }
761 }
762
Jim Millerbbf1a742012-07-17 18:30:30 -0700763 /**
764 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
765 */
Jeff Sharkey054340d2011-09-01 22:28:03 -0700766 private void handleClockVisibilityChanged() {
767 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
Jim Millerbbf1a742012-07-17 18:30:30 -0700768 for (int i = 0; i < mCallbacks.size(); i++) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700769 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
770 if (cb != null) {
771 cb.onClockVisibilityChanged();
772 }
Jeff Sharkey054340d2011-09-01 22:28:03 -0700773 }
774 }
775
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400776 /**
777 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
778 */
779 private void handleKeyguardVisibilityChanged(int showing) {
780 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
Danielle Millett5d2404d2012-11-01 00:05:27 -0400781 boolean isShowing = (showing == 1);
782 mKeyguardIsVisible = isShowing;
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400783 for (int i = 0; i < mCallbacks.size(); i++) {
784 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
785 if (cb != null) {
Danielle Millett5d2404d2012-11-01 00:05:27 -0400786 cb.onKeyguardVisibilityChanged(isShowing);
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400787 }
788 }
789 }
790
Brian Colonna7fce3802013-09-17 15:51:32 -0400791 /**
792 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
793 */
794 private void handleReportEmergencyCallAction() {
795 for (int i = 0; i < mCallbacks.size(); i++) {
796 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
797 if (cb != null) {
798 cb.onEmergencyCallAction();
799 }
800 }
801 }
802
Danielle Millett5d2404d2012-11-01 00:05:27 -0400803 public boolean isKeyguardVisible() {
804 return mKeyguardIsVisible;
805 }
806
Brian Colonnaa5239892013-04-15 11:45:40 -0400807 public boolean isSwitchingUser() {
808 return mSwitchingUser;
809 }
810
Jim Miller16464b82011-10-20 21:10:13 -0700811 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
Jim Millerbbf1a742012-07-17 18:30:30 -0700812 final boolean nowPluggedIn = current.isPluggedIn();
813 final boolean wasPluggedIn = old.isPluggedIn();
Jim Miller79a444a2011-02-15 15:02:11 -0800814 final boolean stateChangedWhilePluggedIn =
Jim Miller16464b82011-10-20 21:10:13 -0700815 wasPluggedIn == true && nowPluggedIn == true
816 && (old.status != current.status);
817
818 // change in plug state is always interesting
819 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800820 return true;
821 }
822
823 // change in battery level while plugged in
Jim Miller16464b82011-10-20 21:10:13 -0700824 if (nowPluggedIn && old.level != current.level) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800825 return true;
826 }
827
Jim Miller16464b82011-10-20 21:10:13 -0700828 // change where battery needs charging
Jim Millerbbf1a742012-07-17 18:30:30 -0700829 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
Jim Miller16464b82011-10-20 21:10:13 -0700830 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800831 }
832 return false;
833 }
834
835 /**
Wink Savillea639b312012-07-10 12:37:54 -0700836 * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800837 * @return The string to use for the plmn, or null if it should not be shown.
838 */
839 private CharSequence getTelephonyPlmnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700840 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
841 final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
Jim Millerbbf1a742012-07-17 18:30:30 -0700842 return (plmn != null) ? plmn : getDefaultPlmn();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800843 }
844 return null;
845 }
846
847 /**
848 * @return The default plmn (no service)
849 */
850 private CharSequence getDefaultPlmn() {
Jim Miller5ecd8112013-01-09 18:50:26 -0800851 return mContext.getResources().getText(R.string.keyguard_carrier_default);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800852 }
853
854 /**
855 * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
856 * @return The string to use for the plmn, or null if it should not be shown.
857 */
858 private CharSequence getTelephonySpnFrom(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700859 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
860 final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800861 if (spn != null) {
862 return spn;
863 }
864 }
865 return null;
866 }
867
868 /**
Jim Millerbbf1a742012-07-17 18:30:30 -0700869 * Remove the given observer's callback.
870 *
Jim Miller6212cc02012-09-05 17:35:31 -0700871 * @param callback The callback to remove
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800872 */
Jim Miller6212cc02012-09-05 17:35:31 -0700873 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
874 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
875 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
876 if (mCallbacks.get(i).get() == callback) {
877 mCallbacks.remove(i);
878 }
879 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800880 }
881
882 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800883 * Register to receive notifications about general keyguard information
884 * (see {@link InfoCallback}.
Jim Miller6212cc02012-09-05 17:35:31 -0700885 * @param callback The callback to register
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800886 */
Jim Millerbbf1a742012-07-17 18:30:30 -0700887 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Jim Miller6212cc02012-09-05 17:35:31 -0700888 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
889 // Prevent adding duplicate callbacks
890 for (int i = 0; i < mCallbacks.size(); i++) {
891 if (mCallbacks.get(i).get() == callback) {
892 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
893 new Exception("Called by"));
894 return;
Jim Millerdcb3d842012-08-23 19:18:12 -0700895 }
896 }
Jim Miller6212cc02012-09-05 17:35:31 -0700897 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
898 removeCallback(null); // remove unused references
899 sendUpdates(callback);
900 }
901
902 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
903 // Notify listener of the current state
904 callback.onRefreshBatteryInfo(mBatteryStatus);
905 callback.onTimeChanged();
906 callback.onRingerModeChanged(mRingMode);
907 callback.onPhoneStateChanged(mPhoneState);
908 callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
909 callback.onClockVisibilityChanged();
910 callback.onSimStateChanged(mSimState);
Jim Miller8f09fd22013-03-14 19:04:28 -0700911 callback.onMusicClientIdChanged(
912 mDisplayClientState.clientGeneration,
913 mDisplayClientState.clearing,
914 mDisplayClientState.intent);
915 callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState,
916 mDisplayClientState.playbackEventTime);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800917 }
918
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400919 public void sendKeyguardVisibilityChanged(boolean showing) {
920 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
921 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
922 message.arg1 = showing ? 1 : 0;
923 message.sendToTarget();
924 }
925
Jeff Sharkey054340d2011-09-01 22:28:03 -0700926 public void reportClockVisible(boolean visible) {
927 mClockVisible = visible;
928 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
929 }
930
Wink Savillea639b312012-07-10 12:37:54 -0700931 public IccCardConstants.State getSimState() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800932 return mSimState;
933 }
934
935 /**
Jim Miller90d5d462011-11-17 16:57:01 -0800936 * 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 -0800937 * have the information earlier than waiting for the intent
938 * broadcast from the telephony code.
Jim Miller90d5d462011-11-17 16:57:01 -0800939 *
940 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
941 * through mHandler, this *must* be called from the UI thread.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800942 */
John Wang0f7b3f82011-05-31 11:20:55 -0700943 public void reportSimUnlocked() {
Wink Savillea639b312012-07-10 12:37:54 -0700944 handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800945 }
946
Brian Colonna7fce3802013-09-17 15:51:32 -0400947 /**
948 * Report that the emergency call button has been pressed and the emergency dialer is
949 * about to be displayed.
950 *
951 * @param bypassHandler runs immediately.
952 *
953 * NOTE: Must be called from UI thread if bypassHandler == true.
954 */
955 public void reportEmergencyCallAction(boolean bypassHandler) {
956 if (!bypassHandler) {
957 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
958 } else {
959 handleReportEmergencyCallAction();
960 }
961 }
962
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800963 public CharSequence getTelephonyPlmn() {
964 return mTelephonyPlmn;
965 }
966
967 public CharSequence getTelephonySpn() {
968 return mTelephonySpn;
969 }
970
971 /**
972 * @return Whether the device is provisioned (whether they have gone through
973 * the setup wizard)
974 */
975 public boolean isDeviceProvisioned() {
976 return mDeviceProvisioned;
977 }
978
Jim Miller258341c2012-08-30 16:50:10 -0700979 public int getFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800980 return mFailedAttempts;
981 }
982
Jim Miller258341c2012-08-30 16:50:10 -0700983 public void clearFailedUnlockAttempts() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800984 mFailedAttempts = 0;
Brian Colonnaea8441e2012-04-25 17:51:49 -0400985 mFailedBiometricUnlockAttempts = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800986 }
987
Jim Miller258341c2012-08-30 16:50:10 -0700988 public void reportFailedUnlockAttempt() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800989 mFailedAttempts++;
990 }
Jim Miller1c188282011-08-08 22:27:58 -0700991
Jeff Sharkey054340d2011-09-01 22:28:03 -0700992 public boolean isClockVisible() {
993 return mClockVisible;
994 }
995
Brian Colonna267cb2b2011-09-26 13:52:25 -0400996 public int getPhoneState() {
997 return mPhoneState;
998 }
Steven Rossb9430d22011-11-23 07:54:09 -0500999
Brian Colonnaea8441e2012-04-25 17:51:49 -04001000 public void reportFailedBiometricUnlockAttempt() {
1001 mFailedBiometricUnlockAttempts++;
Steven Rossb9430d22011-11-23 07:54:09 -05001002 }
1003
Brian Colonnaea8441e2012-04-25 17:51:49 -04001004 public boolean getMaxBiometricUnlockAttemptsReached() {
1005 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
Steven Rossb9430d22011-11-23 07:54:09 -05001006 }
Jim Millerb0304762012-03-13 20:01:25 -07001007
Jim Miller0ff7f012012-10-11 20:40:01 -07001008 public boolean isAlternateUnlockEnabled() {
1009 return mAlternateUnlockEnabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001010 }
1011
Jim Miller0ff7f012012-10-11 20:40:01 -07001012 public void setAlternateUnlockEnabled(boolean enabled) {
1013 mAlternateUnlockEnabled = enabled;
Brian Colonnacc4104f2012-10-09 17:50:46 -04001014 }
1015
Jim Millerb0304762012-03-13 20:01:25 -07001016 public boolean isSimLocked() {
Jim Millerdcb3d842012-08-23 19:18:12 -07001017 return isSimLocked(mSimState);
1018 }
1019
1020 public static boolean isSimLocked(IccCardConstants.State state) {
1021 return state == IccCardConstants.State.PIN_REQUIRED
1022 || state == IccCardConstants.State.PUK_REQUIRED
1023 || state == IccCardConstants.State.PERM_DISABLED;
1024 }
1025
1026 public boolean isSimPinSecure() {
1027 return isSimPinSecure(mSimState);
1028 }
1029
1030 public static boolean isSimPinSecure(IccCardConstants.State state) {
1031 final IccCardConstants.State simState = state;
1032 return (simState == IccCardConstants.State.PIN_REQUIRED
1033 || simState == IccCardConstants.State.PUK_REQUIRED
1034 || simState == IccCardConstants.State.PERM_DISABLED);
Jim Millerb0304762012-03-13 20:01:25 -07001035 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001036
1037 public DisplayClientState getCachedDisplayClientState() {
1038 return mDisplayClientState;
1039 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001040}