blob: 2904f4c6fb86b71f41e280cd22a971cb0ce3fbc0 [file] [log] [blame]
Jim Millerdcb3d842012-08-23 19:18:12 -07001/*
2 * Copyright (C) 2012 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;
18
19import com.android.internal.widget.LockPatternUtils;
20import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
Jim Miller5950bf32013-03-19 17:15:43 -070021import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
Jim Millerdcb3d842012-08-23 19:18:12 -070022
Jim Miller258341c2012-08-30 16:50:10 -070023import android.app.Activity;
Jim Miller95b005c2012-08-29 16:43:32 -070024import android.app.ActivityManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070025import android.app.ActivityOptions;
Jim Miller258341c2012-08-30 16:50:10 -070026import android.app.AlertDialog;
Jim Miller4eeb4f62012-11-08 00:04:29 -080027import android.app.SearchManager;
Jim Miller258341c2012-08-30 16:50:10 -070028import android.app.admin.DevicePolicyManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070029import android.appwidget.AppWidgetHost;
30import android.appwidget.AppWidgetHostView;
31import android.appwidget.AppWidgetManager;
32import android.appwidget.AppWidgetProviderInfo;
Michael Jurkafc753c02012-10-30 18:30:52 -070033import android.content.ComponentName;
Jim Millerdcb3d842012-08-23 19:18:12 -070034import android.content.Context;
35import android.content.Intent;
36import android.content.IntentSender;
Jim Millera75a8832013-02-07 16:53:32 -080037import android.content.pm.PackageManager.NameNotFoundException;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070038import android.content.pm.UserInfo;
Jim Miller95b005c2012-08-29 16:43:32 -070039import android.content.res.Resources;
Jim Millerdcb3d842012-08-23 19:18:12 -070040import android.graphics.Canvas;
Jim Miller57375342012-09-09 15:20:31 -070041import android.graphics.Rect;
Jim Miller8f09fd22013-03-14 19:04:28 -070042import android.media.RemoteControlClient;
Jim Millerf229e4d2012-09-12 20:32:50 -070043import android.os.Looper;
Jim Miller223ce5c2012-10-05 19:13:23 -070044import android.os.Parcel;
45import android.os.Parcelable;
John Spurlockdbe24b72012-11-01 13:01:05 -040046import android.os.SystemClock;
Jim Miller4eeb4f62012-11-08 00:04:29 -080047import android.os.UserHandle;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070048import android.os.UserManager;
Michael Jurkafff56142012-11-28 16:51:00 -080049import android.provider.Settings;
Jim Millerdcb3d842012-08-23 19:18:12 -070050import android.util.AttributeSet;
51import android.util.Log;
Jim Miller258341c2012-08-30 16:50:10 -070052import android.util.Slog;
Jim Millerdcb3d842012-08-23 19:18:12 -070053import android.view.KeyEvent;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070054import android.view.LayoutInflater;
Jim Miller57375342012-09-09 15:20:31 -070055import android.view.MotionEvent;
Jim Millerdcb3d842012-08-23 19:18:12 -070056import android.view.View;
Jim Miller258341c2012-08-30 16:50:10 -070057import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070058import android.view.animation.AnimationUtils;
Jim Millerdcb3d842012-08-23 19:18:12 -070059import android.widget.RemoteViews.OnClickHandler;
60
Jim Miller95b005c2012-08-29 16:43:32 -070061import java.io.File;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070062import java.util.List;
Jim Millerdcb3d842012-08-23 19:18:12 -070063
64public class KeyguardHostView extends KeyguardViewBase {
Jim Miller51117262012-11-04 17:58:09 -080065 private static final String TAG = "KeyguardHostView";
Jim Miller4894a012013-04-03 15:23:55 -070066 // Transport control states.
Jim Miller8f09fd22013-03-14 19:04:28 -070067 static final int TRANSPORT_GONE = 0;
68 static final int TRANSPORT_INVISIBLE = 1;
69 static final int TRANSPORT_VISIBLE = 2;
70
71 private int mTransportState = TRANSPORT_GONE;
Jim Millerff2aa0b2012-09-06 19:03:52 -070072
Jim Millerdcb3d842012-08-23 19:18:12 -070073 // Use this to debug all of keyguard
Jim Millera71984f2012-10-24 22:08:49 -070074 public static boolean DEBUG = KeyguardViewMediator.DEBUG;
Jim Miller8f09fd22013-03-14 19:04:28 -070075 public static boolean DEBUGXPORT = true; // debug music transport control
Jim Millerdcb3d842012-08-23 19:18:12 -070076
Michael Jurka192d6d42012-11-07 01:09:38 -080077 // Found in KeyguardAppWidgetPickActivity.java
Jim Millerdcb3d842012-08-23 19:18:12 -070078 static final int APPWIDGET_HOST_ID = 0x4B455947;
Jim Millerdcb3d842012-08-23 19:18:12 -070079
Michael Jurkaeb963f02012-11-08 00:32:29 -080080 private final int MAX_WIDGETS = 5;
81
Jim Millerdcb3d842012-08-23 19:18:12 -070082 private AppWidgetHost mAppWidgetHost;
Michael Jurka67a871d2012-11-01 18:26:01 -070083 private AppWidgetManager mAppWidgetManager;
Jim Millerf2dfc352012-08-29 18:42:21 -070084 private KeyguardWidgetPager mAppWidgetContainer;
Adam Cohen6fb841f2012-10-24 13:15:38 -070085 private KeyguardSecurityViewFlipper mSecurityViewContainer;
Adam Cohen0a8d3262012-10-03 13:50:55 -070086 private KeyguardSelectorView mKeyguardSelectorView;
Jim Miller4e81bd42012-10-01 20:21:02 -070087 private KeyguardTransportControlView mTransportControl;
Jim Millerdcb3d842012-08-23 19:18:12 -070088 private boolean mIsVerifyUnlockOnly;
Jim Miller258341c2012-08-30 16:50:10 -070089 private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
Jim Miller63f9b812012-10-15 15:58:01 -070090 private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
Michael Jurka76017ca2012-11-06 16:21:09 -080091 private int mAppWidgetToShow;
Jim Millerdcb3d842012-08-23 19:18:12 -070092
Adam Cohenefb3ffb2012-11-06 16:55:32 -080093 private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
Michael Jurka545043e2012-11-21 14:02:34 -080094 private boolean mCleanupAppWidgetsOnBootCompleted = false;
Adam Cohenefb3ffb2012-11-06 16:55:32 -080095
John Spurlock34c4fe52012-11-07 10:12:29 -050096 protected OnDismissAction mDismissAction;
Jim Millerdcb3d842012-08-23 19:18:12 -070097
98 protected int mFailedAttempts;
99 private LockPatternUtils mLockPatternUtils;
100
101 private KeyguardSecurityModel mSecurityModel;
Jim Millerd6523da2012-10-21 16:47:02 -0700102 private KeyguardViewStateManager mViewStateManager;
Jim Millerdcb3d842012-08-23 19:18:12 -0700103
Jim Miller57375342012-09-09 15:20:31 -0700104 private Rect mTempRect = new Rect();
Jim Millerff2aa0b2012-09-06 19:03:52 -0700105
Jim Miller51117262012-11-04 17:58:09 -0800106 private int mDisabledFeatures;
107
108 private boolean mCameraDisabled;
109
110 private boolean mSafeModeEnabled;
111
Michael Jurkafff56142012-11-28 16:51:00 -0800112 private boolean mUserSetupCompleted;
Chris Wrenf41c61b2012-11-29 15:19:54 -0500113
Jim Millera75a8832013-02-07 16:53:32 -0800114 // User for whom this host view was created. Final because we should never change the
115 // id without reconstructing an instance of KeyguardHostView. See note below...
116 private final int mUserId;
Michael Jurkafff56142012-11-28 16:51:00 -0800117
Chris Wrenf41c61b2012-11-29 15:19:54 -0500118 private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
119
Jim Miller8f09fd22013-03-14 19:04:28 -0700120 protected int mClientGeneration;
Jim Miller57375342012-09-09 15:20:31 -0700121
Jim Millere51cf7ae2013-06-25 18:31:56 -0700122 protected boolean mShowSecurityWhenReturn;
123
Adam Cohen24b351a2012-09-14 15:02:27 -0700124 /*package*/ interface UserSwitcherCallback {
125 void hideSecurityView(int duration);
126 void showSecurityView();
Adam Cohen0a8d3262012-10-03 13:50:55 -0700127 void showUnlockHint();
Jim Miller19a52672012-10-23 19:52:04 -0700128 void userActivity();
Adam Cohen24b351a2012-09-14 15:02:27 -0700129 }
130
John Spurlock14adfe42012-11-08 10:29:26 -0500131 /*package*/ interface OnDismissAction {
132 /* returns true if the dismiss should be deferred */
133 boolean onDismiss();
134 }
135
Jim Millerdcb3d842012-08-23 19:18:12 -0700136 public KeyguardHostView(Context context) {
137 this(context, null);
138 }
139
140 public KeyguardHostView(Context context, AttributeSet attrs) {
141 super(context, attrs);
Jim Miller4894a012013-04-03 15:23:55 -0700142
143 if (DEBUG) Log.e(TAG, "KeyguardHostView()");
144
Jim Miller000464a2012-09-04 16:45:06 -0700145 mLockPatternUtils = new LockPatternUtils(context);
Jim Millera75a8832013-02-07 16:53:32 -0800146
147 // Note: This depends on KeyguardHostView getting reconstructed every time the
148 // user switches, since mUserId will be used for the entire session.
149 // Once created, keyguard should *never* re-use this instance with another user.
150 // In other words, mUserId should never change - hence it's marked final.
Amith Yamasanic566b432012-11-30 15:26:21 -0800151 mUserId = mLockPatternUtils.getCurrentUser();
Jim Millera75a8832013-02-07 16:53:32 -0800152
Jim Miller105bedd2013-02-27 21:35:18 -0800153 DevicePolicyManager dpm =
154 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
155 if (dpm != null) {
156 mDisabledFeatures = getDisabledFeatures(dpm);
157 mCameraDisabled = dpm.getCameraDisabled(null);
158 }
159
160 mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
161
162 // These need to be created with the user context...
Jim Millera75a8832013-02-07 16:53:32 -0800163 Context userContext = null;
164 try {
165 final String packageName = "system";
166 userContext = mContext.createPackageContextAsUser(packageName, 0,
167 new UserHandle(mUserId));
168
169 } catch (NameNotFoundException e) {
170 e.printStackTrace();
171 // This should never happen, but it's better to have no widgets than to crash.
172 userContext = context;
173 }
174
Jim Millera75a8832013-02-07 16:53:32 -0800175 mAppWidgetHost = new AppWidgetHost(userContext, APPWIDGET_HOST_ID, mOnClickHandler,
176 Looper.myLooper());
Jim Miller105bedd2013-02-27 21:35:18 -0800177
178 cleanupAppWidgetIds();
179
Jim Millera75a8832013-02-07 16:53:32 -0800180 mAppWidgetManager = AppWidgetManager.getInstance(userContext);
181
Jim Millerf229e4d2012-09-12 20:32:50 -0700182 mSecurityModel = new KeyguardSecurityModel(context);
Jim Miller95b005c2012-08-29 16:43:32 -0700183
Adam Cohend6f89602012-11-06 11:46:25 -0800184 mViewStateManager = new KeyguardViewStateManager(this);
Jim Miller51117262012-11-04 17:58:09 -0800185
Michael Jurkafff56142012-11-28 16:51:00 -0800186 mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
187 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
Jim Miller51117262012-11-04 17:58:09 -0800188
Jim Miller8f09fd22013-03-14 19:04:28 -0700189 // Ensure we have the current state *before* we call showAppropriateWidgetPage()
190 getInitialTransportState();
191
Jim Miller51117262012-11-04 17:58:09 -0800192 if (mSafeModeEnabled) {
193 Log.v(TAG, "Keyguard widgets disabled by safe mode");
194 }
195 if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
196 Log.v(TAG, "Keyguard widgets disabled by DPM");
197 }
198 if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
199 Log.v(TAG, "Keyguard secure camera disabled by DPM");
200 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700201 }
202
Jim Miller8f09fd22013-03-14 19:04:28 -0700203 private void getInitialTransportState() {
204 DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext)
205 .getCachedDisplayClientState();
206 mTransportState = (dcs.clearing ? TRANSPORT_GONE :
207 (isMusicPlaying(dcs.playbackState) ? TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
Jim Miller4894a012013-04-03 15:23:55 -0700208
209 if (DEBUG) Log.v(TAG, "Initial transport state: "
Jim Millerdfb57cd2013-05-30 16:43:53 -0700210 + mTransportState + ", pbstate=" + dcs.playbackState);
Jim Miller8f09fd22013-03-14 19:04:28 -0700211 }
212
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800213 private void cleanupAppWidgetIds() {
Michael Jurka545043e2012-11-21 14:02:34 -0800214 // Since this method may delete a widget (which we can't do until boot completed) we
215 // may have to defer it until after boot complete.
216 if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
217 mCleanupAppWidgetsOnBootCompleted = true;
218 return;
219 }
Michael Jurkafc2dbb22013-02-15 14:17:29 +0100220 if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
221 // Clean up appWidgetIds that are bound to lockscreen, but not actually used
222 // This is only to clean up after another bug: we used to not call
223 // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
224 // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
225 // that are triggered by deleteAppWidgetId, which is why we're doing this
226 int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
227 int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
228 for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
229 int appWidgetId = appWidgetIdsBoundToHost[i];
230 if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
231 Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
232 + appWidgetId);
233 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
234 }
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800235 }
236 }
237 }
238
239 private static boolean contains(int[] array, int target) {
240 for (int value : array) {
241 if (value == target) {
242 return true;
243 }
244 }
245 return false;
246 }
247
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800248 private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
249 new KeyguardUpdateMonitorCallback() {
250 @Override
251 public void onBootCompleted() {
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800252 if (mCheckAppWidgetConsistencyOnBootCompleted) {
253 checkAppWidgetConsistency();
254 mSwitchPageRunnable.run();
255 mCheckAppWidgetConsistencyOnBootCompleted = false;
256 }
Michael Jurka545043e2012-11-21 14:02:34 -0800257 if (mCleanupAppWidgetsOnBootCompleted) {
258 cleanupAppWidgetIds();
259 mCleanupAppWidgetsOnBootCompleted = false;
260 }
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800261 }
Chris Wrenf41c61b2012-11-29 15:19:54 -0500262 @Override
263 public void onUserSwitchComplete(int userId) {
264 if (mKeyguardMultiUserSelectorView != null) {
265 mKeyguardMultiUserSelectorView.finalizeActiveUserView(true);
266 }
267 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700268 @Override
269 void onMusicClientIdChanged(
270 int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
271 // Set transport state to invisible until we know music is playing (below)
272 if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
273 Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration);
274 }
275 mClientGeneration = clientGeneration;
Jim Millerdfb57cd2013-05-30 16:43:53 -0700276 final int newState = (clearing ? TRANSPORT_GONE
277 : (mTransportState == TRANSPORT_VISIBLE ?
278 TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
279 if (newState != mTransportState) {
280 mTransportState = newState;
281 if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
282 KeyguardHostView.this.post(mSwitchPageRunnable);
283 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700284 }
285 @Override
286 public void onMusicPlaybackStateChanged(int playbackState, long eventTime) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700287 if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState);
288 if (mTransportState != TRANSPORT_GONE) {
Jim Millerdfb57cd2013-05-30 16:43:53 -0700289 final int newState = (isMusicPlaying(playbackState) ?
Jim Miller8f09fd22013-03-14 19:04:28 -0700290 TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE);
Jim Millerdfb57cd2013-05-30 16:43:53 -0700291 if (newState != mTransportState) {
292 mTransportState = newState;
293 if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
294 KeyguardHostView.this.post(mSwitchPageRunnable);
295 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700296 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700297 }
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800298 };
299
Jim Miller8f09fd22013-03-14 19:04:28 -0700300 private static final boolean isMusicPlaying(int playbackState) {
301 // This should agree with the list in AudioService.isPlaystateActive()
302 switch (playbackState) {
303 case RemoteControlClient.PLAYSTATE_PLAYING:
304 case RemoteControlClient.PLAYSTATE_BUFFERING:
305 case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
306 case RemoteControlClient.PLAYSTATE_REWINDING:
307 case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
308 case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
309 return true;
310 default:
311 return false;
312 }
313 }
314
Jim Miller2cacda52012-11-07 22:40:20 -0800315 private SlidingChallengeLayout mSlidingChallengeLayout;
316
Jim Millerdcb3d842012-08-23 19:18:12 -0700317 @Override
Jim Millerd2b82f72012-09-18 20:52:55 -0700318 public boolean onTouchEvent(MotionEvent ev) {
319 boolean result = super.onTouchEvent(ev);
Jim Miller57375342012-09-09 15:20:31 -0700320 mTempRect.set(0, 0, 0, 0);
321 offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect);
322 ev.offsetLocation(mTempRect.left, mTempRect.top);
323 result = mSecurityViewContainer.dispatchTouchEvent(ev) || result;
324 ev.offsetLocation(-mTempRect.left, -mTempRect.top);
325 return result;
326 }
327
328 @Override
Jim Millerdcb3d842012-08-23 19:18:12 -0700329 protected void dispatchDraw(Canvas canvas) {
330 super.dispatchDraw(canvas);
Craig Mautner7def1db2012-09-28 10:27:56 -0700331 if (mViewMediatorCallback != null) {
332 mViewMediatorCallback.keyguardDoneDrawing();
333 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700334 }
335
Jim Millerff2aa0b2012-09-06 19:03:52 -0700336 private int getWidgetPosition(int id) {
Jim Miller982d21b2013-05-09 14:43:16 -0700337 final KeyguardWidgetPager appWidgetContainer = mAppWidgetContainer;
338 final int children = appWidgetContainer.getChildCount();
Jim Millerff2aa0b2012-09-06 19:03:52 -0700339 for (int i = 0; i < children; i++) {
Jim Miller982d21b2013-05-09 14:43:16 -0700340 final View content = appWidgetContainer.getWidgetPageAt(i).getContent();
341 if (content != null && content.getId() == id) {
Jim Millerff2aa0b2012-09-06 19:03:52 -0700342 return i;
Jim Miller982d21b2013-05-09 14:43:16 -0700343 } else if (content == null) {
344 // Attempt to track down bug #8886916
345 Log.w(TAG, "*** Null content at " + "i=" + i + ",id=" + id + ",N=" + children);
Jim Millerff2aa0b2012-09-06 19:03:52 -0700346 }
347 }
348 return -1;
349 }
350
Jim Millerdcb3d842012-08-23 19:18:12 -0700351 @Override
352 protected void onFinishInflate() {
Jim Millerd6523da2012-10-21 16:47:02 -0700353 // Grab instances of and make any necessary changes to the main layouts. Create
354 // view state manager and wire up necessary listeners / callbacks.
Winson Chungf3b9ec82012-11-01 14:48:51 -0700355 View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
Jim Millerf2dfc352012-08-29 18:42:21 -0700356 mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
Jim Miller838906b2012-10-19 18:41:25 -0700357 mAppWidgetContainer.setVisibility(VISIBLE);
358 mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
Winson Chungf3b9ec82012-11-01 14:48:51 -0700359 mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
Jim Millerd6523da2012-10-21 16:47:02 -0700360 mAppWidgetContainer.setMinScale(0.5f);
361
Jim Miller2cacda52012-11-07 22:40:20 -0800362 mSlidingChallengeLayout = (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
363 if (mSlidingChallengeLayout != null) {
364 mSlidingChallengeLayout.setOnChallengeScrolledListener(mViewStateManager);
Jim Miller19a52672012-10-23 19:52:04 -0700365 }
Jim Millerd6523da2012-10-21 16:47:02 -0700366 mAppWidgetContainer.setViewStateManager(mViewStateManager);
Michael Jurka1254f2f2012-10-25 11:44:31 -0700367 mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
Jim Millerd6523da2012-10-21 16:47:02 -0700368
Jim Miller2cacda52012-11-07 22:40:20 -0800369 ChallengeLayout challenge = mSlidingChallengeLayout != null ? mSlidingChallengeLayout :
Winson Chung48275d22012-11-05 10:56:31 -0800370 (ChallengeLayout) findViewById(R.id.multi_pane_challenge);
371 challenge.setOnBouncerStateChangedListener(mViewStateManager);
Winson Chung70c2f872012-11-07 21:47:12 -0800372 mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
Jim Millerd6523da2012-10-21 16:47:02 -0700373 mViewStateManager.setPagedView(mAppWidgetContainer);
Winson Chung48275d22012-11-05 10:56:31 -0800374 mViewStateManager.setChallengeLayout(challenge);
Adam Cohen6fb841f2012-10-24 13:15:38 -0700375 mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
Adam Cohen0a8d3262012-10-03 13:50:55 -0700376 mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
Adam Cohen6fb841f2012-10-24 13:15:38 -0700377 mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
Jim Millerff2aa0b2012-09-06 19:03:52 -0700378
John Spurlock03eca852013-03-14 14:21:04 -0400379 setBackButtonEnabled(false);
Jim Miller68c24892012-10-14 05:04:00 -0700380
Michael Jurka67a871d2012-11-01 18:26:01 -0700381 addDefaultWidgets();
Jim Miller9b1db682012-10-25 19:31:19 -0700382
Jim Miller51117262012-11-04 17:58:09 -0800383 addWidgetsFromSettings();
Michael Jurkafff56142012-11-28 16:51:00 -0800384 if (!shouldEnableAddWidget()) {
Winson Chung4752e7d2012-11-20 17:06:04 -0800385 mAppWidgetContainer.setAddWidgetEnabled(false);
Michael Jurkaeb963f02012-11-08 00:32:29 -0800386 }
Jim Miller51117262012-11-04 17:58:09 -0800387 checkAppWidgetConsistency();
388 mSwitchPageRunnable.run();
Adam Cohen45adaa72012-11-02 22:00:57 -0700389 // This needs to be called after the pages are all added.
390 mViewStateManager.showUsabilityHints();
391
Michael Jurka67a871d2012-11-01 18:26:01 -0700392 showPrimarySecurityScreen(false);
Jim Miller9b1db682012-10-25 19:31:19 -0700393 updateSecurityViews();
Jim Millere46efc02012-09-07 16:43:51 -0700394 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700395
John Spurlock03eca852013-03-14 14:21:04 -0400396 private void setBackButtonEnabled(boolean enabled) {
397 if (mContext instanceof Activity) return; // always enabled in activity mode
398 setSystemUiVisibility(enabled ?
399 getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
400 getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
401 }
402
Michael Jurkafff56142012-11-28 16:51:00 -0800403 private boolean shouldEnableAddWidget() {
404 return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
405 }
406
Jim Miller51117262012-11-04 17:58:09 -0800407 private int getDisabledFeatures(DevicePolicyManager dpm) {
408 int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
409 if (dpm != null) {
410 final int currentUser = mLockPatternUtils.getCurrentUser();
411 disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
412 }
413 return disabledFeatures;
414 }
415
416 private boolean widgetsDisabledByDpm() {
417 return (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0;
418 }
419
420 private boolean cameraDisabledByDpm() {
421 return mCameraDisabled
422 || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
423 }
424
Jim Millere46efc02012-09-07 16:43:51 -0700425 private void updateSecurityViews() {
426 int children = mSecurityViewContainer.getChildCount();
427 for (int i = 0; i < children; i++) {
428 updateSecurityView(mSecurityViewContainer.getChildAt(i));
429 }
430 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700431
Jim Millere46efc02012-09-07 16:43:51 -0700432 private void updateSecurityView(View view) {
433 if (view instanceof KeyguardSecurityView) {
434 KeyguardSecurityView ksv = (KeyguardSecurityView) view;
435 ksv.setKeyguardCallback(mCallback);
436 ksv.setLockPatternUtils(mLockPatternUtils);
Chris Wrenc0ae9e62012-11-05 13:16:31 -0500437 if (mViewStateManager.isBouncing()) {
438 ksv.showBouncer(0);
439 } else {
440 ksv.hideBouncer(0);
441 }
Jim Millere46efc02012-09-07 16:43:51 -0700442 } else {
443 Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
Jim Millerdcb3d842012-08-23 19:18:12 -0700444 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700445 }
446
447 void setLockPatternUtils(LockPatternUtils utils) {
448 mSecurityModel.setLockPatternUtils(utils);
449 mLockPatternUtils = utils;
Jim Millere46efc02012-09-07 16:43:51 -0700450 updateSecurityViews();
Jim Millerdcb3d842012-08-23 19:18:12 -0700451 }
452
453 @Override
454 protected void onAttachedToWindow() {
455 super.onAttachedToWindow();
Jim Millera75a8832013-02-07 16:53:32 -0800456 mAppWidgetHost.startListening();
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800457 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
Jim Miller7221d3a2012-10-05 14:34:47 -0700458 }
459
Jim Millerdcb3d842012-08-23 19:18:12 -0700460 @Override
461 protected void onDetachedFromWindow() {
462 super.onDetachedFromWindow();
Jim Millera75a8832013-02-07 16:53:32 -0800463 mAppWidgetHost.stopListening();
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800464 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
Jim Millerdcb3d842012-08-23 19:18:12 -0700465 }
466
Jim Millerd6523da2012-10-21 16:47:02 -0700467 void addWidget(AppWidgetHostView view, int pageIndex) {
468 mAppWidgetContainer.addWidget(view, pageIndex);
Jim Millerdcb3d842012-08-23 19:18:12 -0700469 }
470
Jim Miller838906b2012-10-19 18:41:25 -0700471 private KeyguardWidgetPager.Callbacks mWidgetCallbacks
472 = new KeyguardWidgetPager.Callbacks() {
Jeff Brownc7505bc2012-10-05 21:58:15 -0700473 @Override
474 public void userActivity() {
Adam Cohen08c83ef2012-11-08 00:25:47 -0800475 KeyguardHostView.this.userActivity();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700476 }
477
478 @Override
479 public void onUserActivityTimeoutChanged() {
Adam Cohen08c83ef2012-11-08 00:25:47 -0800480 KeyguardHostView.this.onUserActivityTimeoutChanged();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700481 }
Michael Jurkaeb963f02012-11-08 00:32:29 -0800482
483 @Override
Winson Chung40f82112012-11-08 11:54:55 -0800484 public void onAddView(View v) {
Michael Jurkafff56142012-11-28 16:51:00 -0800485 if (!shouldEnableAddWidget()) {
Winson Chung4752e7d2012-11-20 17:06:04 -0800486 mAppWidgetContainer.setAddWidgetEnabled(false);
Winson Chung40f82112012-11-08 11:54:55 -0800487 }
Winson Chung4752e7d2012-11-20 17:06:04 -0800488 }
Winson Chung40f82112012-11-08 11:54:55 -0800489
490 @Override
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800491 public void onRemoveView(View v, boolean deletePermanently) {
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800492 if (deletePermanently) {
493 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
494 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
495 appWidgetId != LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
496 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
497 }
498 }
Michael Jurkaeb963f02012-11-08 00:32:29 -0800499 }
Winson Chung4752e7d2012-11-20 17:06:04 -0800500
501 @Override
502 public void onRemoveViewAnimationCompleted() {
Michael Jurkafff56142012-11-28 16:51:00 -0800503 if (shouldEnableAddWidget()) {
Winson Chung4752e7d2012-11-20 17:06:04 -0800504 mAppWidgetContainer.setAddWidgetEnabled(true);
505 }
506 }
Jeff Brownc7505bc2012-10-05 21:58:15 -0700507 };
508
Chris Wrenf41c61b2012-11-29 15:19:54 -0500509 public void initializeSwitchingUserState(boolean switching) {
510 if (!switching && mKeyguardMultiUserSelectorView != null) {
511 mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
512 }
513 }
514
Adam Cohen08c83ef2012-11-08 00:25:47 -0800515 public void userActivity() {
516 if (mViewMediatorCallback != null) {
517 mViewMediatorCallback.userActivity();
518 }
519 }
520
521 public void onUserActivityTimeoutChanged() {
522 if (mViewMediatorCallback != null) {
523 mViewMediatorCallback.onUserActivityTimeoutChanged();
524 }
525 }
526
Jeff Brownc7505bc2012-10-05 21:58:15 -0700527 @Override
528 public long getUserActivityTimeout() {
529 // Currently only considering user activity timeouts needed by widgets.
530 // Could also take into account longer timeouts for certain security views.
Jim Miller838906b2012-10-19 18:41:25 -0700531 if (mAppWidgetContainer != null) {
532 return mAppWidgetContainer.getUserActivityTimeout();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700533 }
534 return -1;
535 }
536
Jim Millerdcb3d842012-08-23 19:18:12 -0700537 private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
538
539 public void userActivity(long timeout) {
Craig Mautner7def1db2012-09-28 10:27:56 -0700540 if (mViewMediatorCallback != null) {
Jeff Brown3dc524b2012-09-30 19:49:11 -0700541 mViewMediatorCallback.userActivity(timeout);
Craig Mautner7def1db2012-09-28 10:27:56 -0700542 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700543 }
544
545 public void dismiss(boolean authenticated) {
546 showNextSecurityScreenOrFinish(authenticated);
547 }
548
549 public boolean isVerifyUnlockOnly() {
Jim Miller258341c2012-08-30 16:50:10 -0700550 return mIsVerifyUnlockOnly;
Jim Millerdcb3d842012-08-23 19:18:12 -0700551 }
552
553 public void reportSuccessfulUnlockAttempt() {
Jim Miller258341c2012-08-30 16:50:10 -0700554 KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
Jim Miller76415062012-09-24 18:38:08 -0700555 mLockPatternUtils.reportSuccessfulPasswordAttempt();
Jim Millerdcb3d842012-08-23 19:18:12 -0700556 }
557
558 public void reportFailedUnlockAttempt() {
Jim Miller76415062012-09-24 18:38:08 -0700559 if (mCurrentSecuritySelection == SecurityMode.Biometric) {
560 KeyguardUpdateMonitor.getInstance(mContext).reportFailedBiometricUnlockAttempt();
561 } else {
562 KeyguardHostView.this.reportFailedUnlockAttempt();
563 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700564 }
565
566 public int getFailedAttempts() {
Jim Miller258341c2012-08-30 16:50:10 -0700567 return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
Jim Millerdcb3d842012-08-23 19:18:12 -0700568 }
569
Jim Miller258341c2012-08-30 16:50:10 -0700570 @Override
571 public void showBackupSecurity() {
Jim Miller0ff7f012012-10-11 20:40:01 -0700572 KeyguardHostView.this.showBackupSecurityScreen();
Jim Millerdcb3d842012-08-23 19:18:12 -0700573 }
574
Jim Miller5f75aa12012-08-29 15:10:34 -0700575 @Override
John Spurlock34c4fe52012-11-07 10:12:29 -0500576 public void setOnDismissAction(OnDismissAction action) {
577 KeyguardHostView.this.setOnDismissAction(action);
Jim Miller5f75aa12012-08-29 15:10:34 -0700578 }
579
Jim Millerdcb3d842012-08-23 19:18:12 -0700580 };
581
Jim Miller258341c2012-08-30 16:50:10 -0700582 private void showDialog(String title, String message) {
583 final AlertDialog dialog = new AlertDialog.Builder(mContext)
584 .setTitle(title)
585 .setMessage(message)
Jim Miller5ecd8112013-01-09 18:50:26 -0800586 .setNeutralButton(R.string.ok, null)
Jim Miller258341c2012-08-30 16:50:10 -0700587 .create();
588 if (!(mContext instanceof Activity)) {
589 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
590 }
591 dialog.show();
592 }
593
594 private void showTimeoutDialog() {
595 int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
596 int messageId = 0;
597
598 switch (mSecurityModel.getSecurityMode()) {
599 case Pattern:
600 messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
601 break;
Daniel Sandler69bdee72012-10-23 16:45:50 -0400602 case PIN:
603 messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
604 break;
605 case Password:
606 messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
Jim Miller258341c2012-08-30 16:50:10 -0700607 break;
608 }
609
610 if (messageId != 0) {
611 final String message = mContext.getString(messageId,
612 KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
613 timeoutInSeconds);
614 showDialog(null, message);
615 }
616 }
617
618 private void showAlmostAtWipeDialog(int attempts, int remaining) {
619 int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
620 String message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
621 attempts, remaining);
622 showDialog(null, message);
623 }
624
625 private void showWipeDialog(int attempts) {
626 String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
627 showDialog(null, message);
628 }
629
630 private void showAlmostAtAccountLoginDialog() {
631 final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
632 final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
633 - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
634 String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
635 count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
636 showDialog(null, message);
637 }
638
639 private void reportFailedUnlockAttempt() {
640 final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
641 final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
642
643 if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
644
645 SecurityMode mode = mSecurityModel.getSecurityMode();
646 final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
647
648 final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700649 .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
Jim Miller258341c2012-08-30 16:50:10 -0700650
651 final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
652 - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
653
654 final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
655 (failedAttemptsBeforeWipe - failedAttempts)
656 : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
657
Jim Miller08b2b6b2012-09-14 19:12:40 -0700658 boolean showTimeout = false;
Jim Miller258341c2012-08-30 16:50:10 -0700659 if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
660 // If we reach this code, it means the user has installed a DevicePolicyManager
661 // that requests device wipe after N attempts. Once we get below the grace
662 // period, we'll post this dialog every time as a clear warning until the
663 // bombshell hits and the device is wiped.
664 if (remainingBeforeWipe > 0) {
665 showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
666 } else {
667 // Too many attempts. The device will be wiped shortly.
668 Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
669 showWipeDialog(failedAttempts);
670 }
671 } else {
Jim Miller08b2b6b2012-09-14 19:12:40 -0700672 showTimeout =
Jim Miller258341c2012-08-30 16:50:10 -0700673 (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
674 if (usingPattern && mEnableFallback) {
675 if (failedAttempts == failedAttemptWarning) {
676 showAlmostAtAccountLoginDialog();
677 showTimeout = false; // don't show both dialogs
678 } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
679 mLockPatternUtils.setPermanentlyLocked(true);
Jim Millere46efc02012-09-07 16:43:51 -0700680 showSecurityScreen(SecurityMode.Account);
Jim Miller258341c2012-08-30 16:50:10 -0700681 // don't show timeout dialog because we show account unlock screen next
682 showTimeout = false;
683 }
684 }
Jim Miller258341c2012-08-30 16:50:10 -0700685 }
686 monitor.reportFailedUnlockAttempt();
687 mLockPatternUtils.reportFailedPasswordAttempt();
Jim Miller08b2b6b2012-09-14 19:12:40 -0700688 if (showTimeout) {
689 showTimeoutDialog();
690 }
Jim Miller258341c2012-08-30 16:50:10 -0700691 }
692
693 /**
Jim Miller0ff7f012012-10-11 20:40:01 -0700694 * Shows the primary security screen for the user. This will be either the multi-selector
695 * or the user's security method.
696 * @param turningOff true if the device is being turned off
697 */
698 void showPrimarySecurityScreen(boolean turningOff) {
699 SecurityMode securityMode = mSecurityModel.getSecurityMode();
700 if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
Brian Colonna078f5912012-10-31 20:03:18 -0400701 if (!turningOff &&
702 KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
Jim Miller0ff7f012012-10-11 20:40:01 -0700703 // If we're not turning off, then allow biometric alternate.
704 // We'll reload it when the device comes back on.
705 securityMode = mSecurityModel.getAlternateFor(securityMode);
706 }
707 showSecurityScreen(securityMode);
708 }
Jim Miller68c24892012-10-14 05:04:00 -0700709
Jim Miller0ff7f012012-10-11 20:40:01 -0700710 /**
Jim Miller258341c2012-08-30 16:50:10 -0700711 * Shows the backup security screen for the current security mode. This could be used for
712 * password recovery screens but is currently only used for pattern unlock to show the
713 * account unlock screen and biometric unlock to show the user's normal unlock.
714 */
Jim Miller0ff7f012012-10-11 20:40:01 -0700715 private void showBackupSecurityScreen() {
Danielle Millett61413b52012-10-09 18:07:02 -0400716 if (DEBUG) Log.d(TAG, "showBackupSecurity()");
Jim Miller63f9b812012-10-15 15:58:01 -0700717 SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
718 showSecurityScreen(backup);
Jim Miller258341c2012-08-30 16:50:10 -0700719 }
720
Adam Cohen0a8d3262012-10-03 13:50:55 -0700721 public boolean showNextSecurityScreenIfPresent() {
722 SecurityMode securityMode = mSecurityModel.getSecurityMode();
723 // Allow an alternate, such as biometric unlock
724 securityMode = mSecurityModel.getAlternateFor(securityMode);
725 if (SecurityMode.None == securityMode) {
726 return false;
727 } else {
728 showSecurityScreen(securityMode); // switch to the alternate security view
729 return true;
730 }
731 }
732
Jim Miller258341c2012-08-30 16:50:10 -0700733 private void showNextSecurityScreenOrFinish(boolean authenticated) {
Danielle Millett61413b52012-10-09 18:07:02 -0400734 if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
Jim Millerdcb3d842012-08-23 19:18:12 -0700735 boolean finish = false;
Jim Millere46efc02012-09-07 16:43:51 -0700736 if (SecurityMode.None == mCurrentSecuritySelection) {
Jim Miller258341c2012-08-30 16:50:10 -0700737 SecurityMode securityMode = mSecurityModel.getSecurityMode();
738 // Allow an alternate, such as biometric unlock
Jim Miller000464a2012-09-04 16:45:06 -0700739 securityMode = mSecurityModel.getAlternateFor(securityMode);
Jim Millere46efc02012-09-07 16:43:51 -0700740 if (SecurityMode.None == securityMode) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700741 finish = true; // no security required
742 } else {
Jim Millere46efc02012-09-07 16:43:51 -0700743 showSecurityScreen(securityMode); // switch to the alternate security view
Jim Millerdcb3d842012-08-23 19:18:12 -0700744 }
745 } else if (authenticated) {
Jim Millere46efc02012-09-07 16:43:51 -0700746 switch (mCurrentSecuritySelection) {
747 case Pattern:
748 case Password:
Daniel Sandler69bdee72012-10-23 16:45:50 -0400749 case PIN:
Jim Millere46efc02012-09-07 16:43:51 -0700750 case Account:
751 case Biometric:
Jim Miller4b09dd32012-09-04 14:27:25 -0700752 finish = true;
753 break;
754
Jim Millere46efc02012-09-07 16:43:51 -0700755 case SimPin:
756 case SimPuk:
Jim Miller4b09dd32012-09-04 14:27:25 -0700757 // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
758 SecurityMode securityMode = mSecurityModel.getSecurityMode();
759 if (securityMode != SecurityMode.None) {
Jim Millere46efc02012-09-07 16:43:51 -0700760 showSecurityScreen(securityMode);
Jim Miller4b09dd32012-09-04 14:27:25 -0700761 } else {
762 finish = true;
763 }
764 break;
765
766 default:
Jim Miller0ff7f012012-10-11 20:40:01 -0700767 Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
768 showPrimarySecurityScreen(false);
Jim Miller4b09dd32012-09-04 14:27:25 -0700769 break;
Jim Millerdcb3d842012-08-23 19:18:12 -0700770 }
771 } else {
Jim Miller0ff7f012012-10-11 20:40:01 -0700772 showPrimarySecurityScreen(false);
Jim Millerdcb3d842012-08-23 19:18:12 -0700773 }
774 if (finish) {
Jim Miller0ff7f012012-10-11 20:40:01 -0700775 // If the alternate unlock was suppressed, it can now be safely
776 // enabled because the user has left keyguard.
777 KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
Jim Miller68c24892012-10-14 05:04:00 -0700778
Jim Millerdcb3d842012-08-23 19:18:12 -0700779 // If there's a pending runnable because the user interacted with a widget
780 // and we're leaving keyguard, then run it.
John Spurlock34c4fe52012-11-07 10:12:29 -0500781 boolean deferKeyguardDone = false;
782 if (mDismissAction != null) {
783 deferKeyguardDone = mDismissAction.onDismiss();
784 mDismissAction = null;
Jim Millerdcb3d842012-08-23 19:18:12 -0700785 }
Craig Mautner7def1db2012-09-28 10:27:56 -0700786 if (mViewMediatorCallback != null) {
John Spurlock34c4fe52012-11-07 10:12:29 -0500787 if (deferKeyguardDone) {
788 mViewMediatorCallback.keyguardDonePending();
789 } else {
790 mViewMediatorCallback.keyguardDone(true);
791 }
Craig Mautner7def1db2012-09-28 10:27:56 -0700792 }
Jim Millerb5f3b702012-10-21 19:09:23 -0700793 } else {
794 mViewStateManager.showBouncer(true);
Jim Millerdcb3d842012-08-23 19:18:12 -0700795 }
796 }
797
798 private OnClickHandler mOnClickHandler = new OnClickHandler() {
799 @Override
800 public boolean onClickHandler(final View view,
801 final android.app.PendingIntent pendingIntent,
802 final Intent fillInIntent) {
803 if (pendingIntent.isActivity()) {
John Spurlock34c4fe52012-11-07 10:12:29 -0500804 setOnDismissAction(new OnDismissAction() {
805 public boolean onDismiss() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700806 try {
807 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
808 Context context = view.getContext();
809 ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
810 0, 0,
811 view.getMeasuredWidth(), view.getMeasuredHeight());
812 context.startIntentSender(
813 pendingIntent.getIntentSender(), fillInIntent,
814 Intent.FLAG_ACTIVITY_NEW_TASK,
815 Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
John Spurlock34c4fe52012-11-07 10:12:29 -0500816 } catch (IntentSender.SendIntentException e) {
817 android.util.Log.e(TAG, "Cannot send pending intent: ", e);
818 } catch (Exception e) {
819 android.util.Log.e(TAG, "Cannot send pending intent due to " +
820 "unknown exception: ", e);
821 }
822 return false;
Jim Millerdcb3d842012-08-23 19:18:12 -0700823 }
Jim Miller5f75aa12012-08-29 15:10:34 -0700824 });
Jim Millerdcb3d842012-08-23 19:18:12 -0700825
Jim Miller08898372012-11-04 19:08:40 -0800826 if (mViewStateManager.isChallengeShowing()) {
827 mViewStateManager.showBouncer(true);
828 } else {
829 mCallback.dismiss(false);
830 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700831 return true;
832 } else {
833 return super.onClickHandler(view, pendingIntent, fillInIntent);
834 }
835 };
836 };
837
Jim Miller63f9b812012-10-15 15:58:01 -0700838 // Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
839 // This avoids unwanted asynchronous events from messing with the state.
840 private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
841
842 @Override
843 public void userActivity(long timeout) {
844 }
845
846 @Override
847 public void showBackupSecurity() {
848 }
849
850 @Override
John Spurlock34c4fe52012-11-07 10:12:29 -0500851 public void setOnDismissAction(OnDismissAction action) {
Jim Miller63f9b812012-10-15 15:58:01 -0700852 }
853
854 @Override
855 public void reportSuccessfulUnlockAttempt() {
856 }
857
858 @Override
859 public void reportFailedUnlockAttempt() {
860 }
861
862 @Override
863 public boolean isVerifyUnlockOnly() {
864 return false;
865 }
866
867 @Override
868 public int getFailedAttempts() {
869 return 0;
870 }
871
872 @Override
873 public void dismiss(boolean securityVerified) {
874 }
875 };
876
Jim Miller5f75aa12012-08-29 15:10:34 -0700877 /**
John Spurlock34c4fe52012-11-07 10:12:29 -0500878 * Sets an action to perform when keyguard is dismissed.
879 * @param action
Jim Miller5f75aa12012-08-29 15:10:34 -0700880 */
John Spurlock34c4fe52012-11-07 10:12:29 -0500881 protected void setOnDismissAction(OnDismissAction action) {
882 mDismissAction = action;
Jim Miller5f75aa12012-08-29 15:10:34 -0700883 }
884
Jim Millere46efc02012-09-07 16:43:51 -0700885 private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
886 final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
887 KeyguardSecurityView view = null;
888 final int children = mSecurityViewContainer.getChildCount();
Jim Millerdcb3d842012-08-23 19:18:12 -0700889 for (int child = 0; child < children; child++) {
Jim Millere46efc02012-09-07 16:43:51 -0700890 if (mSecurityViewContainer.getChildAt(child).getId() == securityViewIdForMode) {
891 view = ((KeyguardSecurityView)mSecurityViewContainer.getChildAt(child));
892 break;
Jim Millerdcb3d842012-08-23 19:18:12 -0700893 }
894 }
Jim Miller63f9b812012-10-15 15:58:01 -0700895 int layoutId = getLayoutIdFor(securityMode);
896 if (view == null && layoutId != 0) {
Jim Millere46efc02012-09-07 16:43:51 -0700897 final LayoutInflater inflater = LayoutInflater.from(mContext);
Jim Millerbdffd5c2012-10-15 22:11:52 -0700898 if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
Adam Powell97997142012-11-06 21:32:42 -0800899 View v = inflater.inflate(layoutId, mSecurityViewContainer, false);
Jim Millere46efc02012-09-07 16:43:51 -0700900 mSecurityViewContainer.addView(v);
901 updateSecurityView(v);
Jim Miller0b728242012-10-28 19:42:30 -0700902 view = (KeyguardSecurityView)v;
Jim Millere46efc02012-09-07 16:43:51 -0700903 }
Jim Miller0ff7f012012-10-11 20:40:01 -0700904
Jim Miller0ff7f012012-10-11 20:40:01 -0700905 if (view instanceof KeyguardSelectorView) {
906 KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
907 View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
908 selectorView.setCarrierArea(carrierText);
909 }
Jim Miller68c24892012-10-14 05:04:00 -0700910
Jim Millere46efc02012-09-07 16:43:51 -0700911 return view;
Jim Millerdcb3d842012-08-23 19:18:12 -0700912 }
913
Jim Miller258341c2012-08-30 16:50:10 -0700914 /**
915 * Switches to the given security view unless it's already being shown, in which case
916 * this is a no-op.
917 *
Jim Millere46efc02012-09-07 16:43:51 -0700918 * @param securityMode
Jim Miller258341c2012-08-30 16:50:10 -0700919 */
Jim Millere46efc02012-09-07 16:43:51 -0700920 private void showSecurityScreen(SecurityMode securityMode) {
Jim Miller68c24892012-10-14 05:04:00 -0700921 if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
922
Jim Millere46efc02012-09-07 16:43:51 -0700923 if (securityMode == mCurrentSecuritySelection) return;
Jim Millerdcb3d842012-08-23 19:18:12 -0700924
Jim Millere46efc02012-09-07 16:43:51 -0700925 KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
926 KeyguardSecurityView newView = getSecurityView(securityMode);
Jim Millerdcb3d842012-08-23 19:18:12 -0700927
Jim Millera71984f2012-10-24 22:08:49 -0700928 // Enter full screen mode if we're in SIM or Account screen
Jim Miller5ecd8112013-01-09 18:50:26 -0800929 boolean fullScreenEnabled = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
Jim Millera71984f2012-10-24 22:08:49 -0700930 boolean isSimOrAccount = securityMode == SecurityMode.SimPin
931 || securityMode == SecurityMode.SimPuk
932 || securityMode == SecurityMode.Account;
933 mAppWidgetContainer.setVisibility(
934 isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE);
935
Jim Miller2cacda52012-11-07 22:40:20 -0800936 if (mSlidingChallengeLayout != null) {
937 mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled);
938 }
939
Jim Millerdcb3d842012-08-23 19:18:12 -0700940 // Emulate Activity life cycle
Jim Miller63f9b812012-10-15 15:58:01 -0700941 if (oldView != null) {
942 oldView.onPause();
943 oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
944 }
Chris Wrena042ac92012-11-07 11:37:06 -0500945 newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
Jim Miller63f9b812012-10-15 15:58:01 -0700946 newView.setKeyguardCallback(mCallback);
Jim Millerdcb3d842012-08-23 19:18:12 -0700947
Craig Mautnercd03a262012-09-28 11:54:09 -0700948 final boolean needsInput = newView.needsInput();
Craig Mautner7def1db2012-09-28 10:27:56 -0700949 if (mViewMediatorCallback != null) {
Craig Mautnercd03a262012-09-28 11:54:09 -0700950 mViewMediatorCallback.setNeedsInput(needsInput);
Craig Mautner7def1db2012-09-28 10:27:56 -0700951 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700952
953 // Find and show this child.
Jim Millere46efc02012-09-07 16:43:51 -0700954 final int childCount = mSecurityViewContainer.getChildCount();
Jim Miller4b09dd32012-09-04 14:27:25 -0700955
Jim Miller22ae05d2012-10-30 20:37:57 -0700956 mSecurityViewContainer.setInAnimation(
957 AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
958 mSecurityViewContainer.setOutAnimation(
959 AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
Jim Millere46efc02012-09-07 16:43:51 -0700960 final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
Jim Millerdcb3d842012-08-23 19:18:12 -0700961 for (int i = 0; i < childCount; i++) {
Jim Millere46efc02012-09-07 16:43:51 -0700962 if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
963 mSecurityViewContainer.setDisplayedChild(i);
Jim Millerdcb3d842012-08-23 19:18:12 -0700964 break;
965 }
966 }
Jim Miller258341c2012-08-30 16:50:10 -0700967
Jim Millere46efc02012-09-07 16:43:51 -0700968 if (securityMode == SecurityMode.None) {
Jim Millere23ab8b2012-09-16 15:45:44 -0700969 // Discard current runnable if we're switching back to the selector view
John Spurlock34c4fe52012-11-07 10:12:29 -0500970 setOnDismissAction(null);
Jim Miller68c24892012-10-14 05:04:00 -0700971 }
John Spurlock03eca852013-03-14 14:21:04 -0400972 if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
973 // we're showing account as a backup, provide a way to get back to primary
974 setBackButtonEnabled(true);
975 }
Jim Millere46efc02012-09-07 16:43:51 -0700976 mCurrentSecuritySelection = securityMode;
Jim Millerdcb3d842012-08-23 19:18:12 -0700977 }
978
979 @Override
980 public void onScreenTurnedOn() {
John Spurlock358148e2012-10-26 15:29:59 -0400981 if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
Jim Miller0ff7f012012-10-11 20:40:01 -0700982 showPrimarySecurityScreen(false);
Chris Wrena042ac92012-11-07 11:37:06 -0500983 getSecurityView(mCurrentSecuritySelection).onResume(KeyguardSecurityView.SCREEN_ON);
Jim Millerd03a5552012-09-10 20:46:36 -0700984
985 // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
986 // layout is blank but forcing a layout causes it to reappear (e.g. with with
987 // hierarchyviewer).
988 requestLayout();
Adam Cohen6fb841f2012-10-24 13:15:38 -0700989
990 if (mViewStateManager != null) {
991 mViewStateManager.showUsabilityHints();
992 }
Jim Miller147f9562012-12-03 17:55:16 -0800993 requestFocus();
Jim Millerdcb3d842012-08-23 19:18:12 -0700994 }
995
996 @Override
997 public void onScreenTurnedOff() {
John Spurlockdbe24b72012-11-01 13:01:05 -0400998 if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
999 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
Brian Colonna078f5912012-10-31 20:03:18 -04001000 // Once the screen turns off, we no longer consider this to be first boot and we want the
1001 // biometric unlock to start next time keyguard is shown.
1002 KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
Michael Jurka14138892012-11-07 13:45:53 -08001003 // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
1004 // turns off we reset that behavior
1005 clearAppWidgetToShow();
Michael Jurka67a871d2012-11-01 18:26:01 -07001006 checkAppWidgetConsistency();
Jim Miller0ff7f012012-10-11 20:40:01 -07001007 showPrimarySecurityScreen(true);
Jim Millere46efc02012-09-07 16:43:51 -07001008 getSecurityView(mCurrentSecuritySelection).onPause();
John Spurlockdbe24b72012-11-01 13:01:05 -04001009 CameraWidgetFrame cameraPage = findCameraPage();
1010 if (cameraPage != null) {
1011 cameraPage.onScreenTurnedOff();
1012 }
Jim Miller147f9562012-12-03 17:55:16 -08001013 clearFocus();
Jim Millerdcb3d842012-08-23 19:18:12 -07001014 }
1015
Michael Jurka14138892012-11-07 13:45:53 -08001016 public void clearAppWidgetToShow() {
1017 mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1018 }
1019
Jim Millerdcb3d842012-08-23 19:18:12 -07001020 @Override
1021 public void show() {
Jim Miller08697702012-10-22 16:49:52 -07001022 if (DEBUG) Log.d(TAG, "show()");
1023 showPrimarySecurityScreen(false);
Jim Millerdcb3d842012-08-23 19:18:12 -07001024 }
1025
Jim Millerdcb3d842012-08-23 19:18:12 -07001026 @Override
1027 public void verifyUnlock() {
1028 SecurityMode securityMode = mSecurityModel.getSecurityMode();
1029 if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
Craig Mautner7def1db2012-09-28 10:27:56 -07001030 if (mViewMediatorCallback != null) {
1031 mViewMediatorCallback.keyguardDone(true);
1032 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001033 } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
Daniel Sandler69bdee72012-10-23 16:45:50 -04001034 && securityMode != KeyguardSecurityModel.SecurityMode.PIN
Jim Millerdcb3d842012-08-23 19:18:12 -07001035 && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
1036 // can only verify unlock when in pattern/password mode
Craig Mautner7def1db2012-09-28 10:27:56 -07001037 if (mViewMediatorCallback != null) {
1038 mViewMediatorCallback.keyguardDone(false);
1039 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001040 } else {
1041 // otherwise, go to the unlock screen, see if they can verify it
1042 mIsVerifyUnlockOnly = true;
Jim Millere46efc02012-09-07 16:43:51 -07001043 showSecurityScreen(securityMode);
Jim Millerdcb3d842012-08-23 19:18:12 -07001044 }
1045 }
1046
1047 private int getSecurityViewIdForMode(SecurityMode securityMode) {
1048 switch (securityMode) {
Jim Millere46efc02012-09-07 16:43:51 -07001049 case None: return R.id.keyguard_selector_view;
1050 case Pattern: return R.id.keyguard_pattern_view;
Daniel Sandler69bdee72012-10-23 16:45:50 -04001051 case PIN: return R.id.keyguard_pin_view;
Jim Millere46efc02012-09-07 16:43:51 -07001052 case Password: return R.id.keyguard_password_view;
1053 case Biometric: return R.id.keyguard_face_unlock_view;
1054 case Account: return R.id.keyguard_account_view;
1055 case SimPin: return R.id.keyguard_sim_pin_view;
1056 case SimPuk: return R.id.keyguard_sim_puk_view;
Jim Millerdcb3d842012-08-23 19:18:12 -07001057 }
1058 return 0;
1059 }
1060
Jim Millere46efc02012-09-07 16:43:51 -07001061 private int getLayoutIdFor(SecurityMode securityMode) {
1062 switch (securityMode) {
1063 case None: return R.layout.keyguard_selector_view;
1064 case Pattern: return R.layout.keyguard_pattern_view;
Daniel Sandler69bdee72012-10-23 16:45:50 -04001065 case PIN: return R.layout.keyguard_pin_view;
Jim Millere46efc02012-09-07 16:43:51 -07001066 case Password: return R.layout.keyguard_password_view;
1067 case Biometric: return R.layout.keyguard_face_unlock_view;
1068 case Account: return R.layout.keyguard_account_view;
1069 case SimPin: return R.layout.keyguard_sim_pin_view;
1070 case SimPuk: return R.layout.keyguard_sim_puk_view;
1071 default:
Jim Miller63f9b812012-10-15 15:58:01 -07001072 return 0;
Jim Millere46efc02012-09-07 16:43:51 -07001073 }
1074 }
1075
Jim Miller51117262012-11-04 17:58:09 -08001076 private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
Michael Jurka67a871d2012-11-01 18:26:01 -07001077 AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
Jim Miller99a3cae2012-09-17 20:53:51 -07001078 if (appWidgetInfo != null) {
Jim Millera75a8832013-02-07 16:53:32 -08001079 AppWidgetHostView view = mAppWidgetHost.createView(mContext, appId, appWidgetInfo);
Jim Millerd6523da2012-10-21 16:47:02 -07001080 addWidget(view, pageIndex);
Michael Jurka67a871d2012-11-01 18:26:01 -07001081 return true;
Jim Miller99a3cae2012-09-17 20:53:51 -07001082 } else {
Jim Miller51117262012-11-04 17:58:09 -08001083 if (updateDbIfFailed) {
Jim Millera75a8832013-02-07 16:53:32 -08001084 Log.w(TAG, "*** AppWidgetInfo for app widget id " + appId + " was null for user"
1085 + mUserId + ", deleting");
Jim Miller51117262012-11-04 17:58:09 -08001086 mAppWidgetHost.deleteAppWidgetId(appId);
1087 mLockPatternUtils.removeAppWidget(appId);
1088 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001089 return false;
Jim Miller99a3cae2012-09-17 20:53:51 -07001090 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001091 }
1092
John Spurlockdcc96812012-10-25 14:35:19 -04001093 private final CameraWidgetFrame.Callbacks mCameraWidgetCallbacks =
1094 new CameraWidgetFrame.Callbacks() {
1095 @Override
1096 public void onLaunchingCamera() {
John Spurlock57f928f2012-11-02 13:09:25 -04001097 setSliderHandleAlpha(0);
John Spurlockdcc96812012-10-25 14:35:19 -04001098 }
1099
1100 @Override
John Spurlock57f928f2012-11-02 13:09:25 -04001101 public void onCameraLaunchedSuccessfully() {
Winson Chung6cf53bb2012-11-05 17:55:42 -08001102 if (mAppWidgetContainer.isCameraPage(mAppWidgetContainer.getCurrentPage())) {
John Spurlock4b976ea2012-10-28 12:34:11 -04001103 mAppWidgetContainer.scrollLeft();
1104 }
John Spurlock57f928f2012-11-02 13:09:25 -04001105 setSliderHandleAlpha(1);
Jim Milleraaf9b112012-10-31 19:44:56 -07001106 mShowSecurityWhenReturn = true;
John Spurlockdcc96812012-10-25 14:35:19 -04001107 }
1108
John Spurlock57f928f2012-11-02 13:09:25 -04001109 @Override
1110 public void onCameraLaunchedUnsuccessfully() {
1111 setSliderHandleAlpha(1);
1112 }
1113
1114 private void setSliderHandleAlpha(float alpha) {
1115 SlidingChallengeLayout slider =
1116 (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
1117 if (slider != null) {
1118 slider.setHandleAlpha(alpha);
1119 }
John Spurlockdcc96812012-10-25 14:35:19 -04001120 }
1121 };
1122
1123 private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
1124 @Override
1125 Context getContext() {
1126 return mContext;
1127 }
1128
1129 @Override
1130 KeyguardSecurityCallback getCallback() {
1131 return mCallback;
1132 }
1133
1134 @Override
1135 LockPatternUtils getLockPatternUtils() {
1136 return mLockPatternUtils;
Jim Millerbdca3c02012-10-29 19:11:50 -07001137 }
1138 };
John Spurlockdcc96812012-10-25 14:35:19 -04001139
Michael Jurkaeb963f02012-11-08 00:32:29 -08001140 private int numWidgets() {
1141 final int childCount = mAppWidgetContainer.getChildCount();
1142 int widgetCount = 0;
1143 for (int i = 0; i < childCount; i++) {
1144 if (mAppWidgetContainer.isWidgetPage(i)) {
1145 widgetCount++;
1146 }
1147 }
1148 return widgetCount;
1149 }
1150
Jim Miller4e81bd42012-10-01 20:21:02 -07001151 private void addDefaultWidgets() {
Jim Miller51117262012-11-04 17:58:09 -08001152 if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
Jim Miller8f09fd22013-03-14 19:04:28 -07001153 LayoutInflater inflater = LayoutInflater.from(mContext);
Jim Miller51117262012-11-04 17:58:09 -08001154 View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
Michael Jurkaeb963f02012-11-08 00:32:29 -08001155 mAppWidgetContainer.addWidget(addWidget, 0);
Jim Miller51117262012-11-04 17:58:09 -08001156 View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
1157 addWidgetButton.setOnClickListener(new OnClickListener() {
1158 @Override
1159 public void onClick(View v) {
Michael Jurka192d6d42012-11-07 01:09:38 -08001160 // Pass in an invalid widget id... the picker will allocate an ID for us
1161 mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
Jim Miller51117262012-11-04 17:58:09 -08001162 }
1163 });
1164 }
1165
1166 // We currently disable cameras in safe mode because we support loading 3rd party
1167 // cameras we can't trust. TODO: plumb safe mode into camera creation code and only
1168 // inflate system-provided camera?
John Spurlock371f3402012-11-30 09:20:43 -05001169 if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
Jim Miller51117262012-11-04 17:58:09 -08001170 && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
John Spurlockdcc96812012-10-25 14:35:19 -04001171 View cameraWidget =
1172 CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
1173 if (cameraWidget != null) {
1174 mAppWidgetContainer.addWidget(cameraWidget);
1175 }
John Spurlock86b63572012-10-24 11:24:25 -04001176 }
Jim Miller838906b2012-10-19 18:41:25 -07001177
Jim Miller19a52672012-10-23 19:52:04 -07001178 enableUserSelectorIfNecessary();
Jim Miller7221d3a2012-10-05 14:34:47 -07001179 }
1180
Jim Miller8f09fd22013-03-14 19:04:28 -07001181 /**
1182 * Create KeyguardTransportControlView on demand.
1183 * @return
1184 */
Jim Miller4894a012013-04-03 15:23:55 -07001185 private KeyguardTransportControlView getOrCreateTransportControl() {
Jim Miller8f09fd22013-03-14 19:04:28 -07001186 if (mTransportControl == null) {
1187 LayoutInflater inflater = LayoutInflater.from(mContext);
1188 mTransportControl = (KeyguardTransportControlView)
1189 inflater.inflate(R.layout.keyguard_transport_control_view, this, false);
Jim Millerbdca3c02012-10-29 19:11:50 -07001190 }
Jim Miller8f09fd22013-03-14 19:04:28 -07001191 return mTransportControl;
Jim Miller4e81bd42012-10-01 20:21:02 -07001192 }
1193
Jim Miller51117262012-11-04 17:58:09 -08001194 private int getInsertPageIndex() {
Michael Jurka67a871d2012-11-01 18:26:01 -07001195 View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
Jim Miller51117262012-11-04 17:58:09 -08001196 int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget);
1197 if (insertionIndex < 0) {
1198 insertionIndex = 0; // no add widget page found
1199 } else {
1200 insertionIndex++; // place after add widget
Michael Jurka67a871d2012-11-01 18:26:01 -07001201 }
Jim Miller51117262012-11-04 17:58:09 -08001202 return insertionIndex;
Michael Jurka67a871d2012-11-01 18:26:01 -07001203 }
1204
1205 private void addDefaultStatusWidget(int index) {
1206 LayoutInflater inflater = LayoutInflater.from(mContext);
1207 View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
1208 mAppWidgetContainer.addWidget(statusWidget, index);
1209 }
1210
Michael Jurka1254f2f2012-10-25 11:44:31 -07001211 private void addWidgetsFromSettings() {
Jim Miller51117262012-11-04 17:58:09 -08001212 if (mSafeModeEnabled || widgetsDisabledByDpm()) {
1213 return;
Jim Millerb8ec4702012-08-31 17:19:10 -07001214 }
Jim Millerf229e4d2012-09-12 20:32:50 -07001215
Jim Miller51117262012-11-04 17:58:09 -08001216 int insertionIndex = getInsertPageIndex();
Michael Jurka20c41d52012-09-20 19:01:06 -07001217
1218 // Add user-selected widget
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001219 final int[] widgets = mLockPatternUtils.getAppWidgets();
Michael Jurka67a871d2012-11-01 18:26:01 -07001220
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001221 if (widgets == null) {
1222 Log.d(TAG, "Problem reading widgets");
1223 } else {
1224 for (int i = widgets.length -1; i >= 0; i--) {
Michael Jurka1254f2f2012-10-25 11:44:31 -07001225 if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
Jim Miller51117262012-11-04 17:58:09 -08001226 addDefaultStatusWidget(insertionIndex);
Michael Jurka1254f2f2012-10-25 11:44:31 -07001227 } else {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001228 // We add the widgets from left to right, starting after the first page after
1229 // the add page. We count down, since the order will be persisted from right
1230 // to left, starting after camera.
Jim Miller51117262012-11-04 17:58:09 -08001231 addWidget(widgets[i], insertionIndex, true);
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001232 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001233 }
1234 }
Jim Miller51117262012-11-04 17:58:09 -08001235 }
1236
1237 private int allocateIdForDefaultAppWidget() {
1238 int appWidgetId;
1239 Resources res = getContext().getResources();
1240 ComponentName defaultAppWidget = new ComponentName(
1241 res.getString(R.string.widget_default_package_name),
1242 res.getString(R.string.widget_default_class_name));
1243
1244 // Note: we don't support configuring the widget
1245 appWidgetId = mAppWidgetHost.allocateAppWidgetId();
1246
1247 try {
1248 mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
1249
1250 } catch (IllegalArgumentException e) {
1251 Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
1252 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
1253 appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
1254 }
1255 return appWidgetId;
Michael Jurka67a871d2012-11-01 18:26:01 -07001256 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001257 public void checkAppWidgetConsistency() {
Adam Cohenefb3ffb2012-11-06 16:55:32 -08001258 // Since this method may bind a widget (which we can't do until boot completed) we
1259 // may have to defer it until after boot complete.
Adam Cohen4eb36cf2012-11-07 11:45:30 -08001260 if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
Adam Cohenefb3ffb2012-11-06 16:55:32 -08001261 mCheckAppWidgetConsistencyOnBootCompleted = true;
1262 return;
1263 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001264 final int childCount = mAppWidgetContainer.getChildCount();
1265 boolean widgetPageExists = false;
1266 for (int i = 0; i < childCount; i++) {
Jim Miller51117262012-11-04 17:58:09 -08001267 if (mAppWidgetContainer.isWidgetPage(i)) {
Michael Jurka67a871d2012-11-01 18:26:01 -07001268 widgetPageExists = true;
1269 break;
1270 }
1271 }
1272 if (!widgetPageExists) {
Jim Miller51117262012-11-04 17:58:09 -08001273 final int insertPageIndex = getInsertPageIndex();
Michael Jurka67a871d2012-11-01 18:26:01 -07001274
Jim Miller51117262012-11-04 17:58:09 -08001275 final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm();
1276 boolean addedDefaultAppWidget = false;
Michael Jurka67a871d2012-11-01 18:26:01 -07001277
Jim Miller51117262012-11-04 17:58:09 -08001278 if (!mSafeModeEnabled) {
1279 if (userAddedWidgetsEnabled) {
1280 int appWidgetId = allocateIdForDefaultAppWidget();
1281 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1282 addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true);
1283 }
1284 } else {
1285 // note: even if widgetsDisabledByDpm() returns true, we still bind/create
1286 // the default appwidget if possible
1287 int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId();
1288 if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
1289 appWidgetId = allocateIdForDefaultAppWidget();
1290 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1291 mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId);
1292 }
1293 }
1294 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1295 addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false);
1296 if (!addedDefaultAppWidget) {
1297 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
1298 mLockPatternUtils.writeFallbackAppWidgetId(
1299 AppWidgetManager.INVALID_APPWIDGET_ID);
1300 }
1301 }
1302 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001303 }
Jim Miller51117262012-11-04 17:58:09 -08001304
Michael Jurka67a871d2012-11-01 18:26:01 -07001305 // Use the built-in status/clock view if we can't inflate the default widget
Jim Miller51117262012-11-04 17:58:09 -08001306 if (!addedDefaultAppWidget) {
1307 addDefaultStatusWidget(insertPageIndex);
Michael Jurka67a871d2012-11-01 18:26:01 -07001308 }
Jim Miller51117262012-11-04 17:58:09 -08001309
1310 // trigger DB updates only if user-added widgets are enabled
1311 if (!mSafeModeEnabled && userAddedWidgetsEnabled) {
1312 mAppWidgetContainer.onAddView(
1313 mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
1314 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001315 }
Adam Cohen0207c092012-09-30 16:11:00 -07001316 }
1317
Jim Miller223ce5c2012-10-05 19:13:23 -07001318 Runnable mSwitchPageRunnable = new Runnable() {
1319 @Override
1320 public void run() {
1321 showAppropriateWidgetPage();
Adam Cohen0207c092012-09-30 16:11:00 -07001322 }
Jim Miller223ce5c2012-10-05 19:13:23 -07001323 };
1324
1325 static class SavedState extends BaseSavedState {
1326 int transportState;
Michael Jurka14138892012-11-07 13:45:53 -08001327 int appWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
Jim Miller223ce5c2012-10-05 19:13:23 -07001328
1329 SavedState(Parcelable superState) {
1330 super(superState);
1331 }
1332
1333 private SavedState(Parcel in) {
1334 super(in);
1335 this.transportState = in.readInt();
Michael Jurka14138892012-11-07 13:45:53 -08001336 this.appWidgetToShow = in.readInt();
Jim Miller223ce5c2012-10-05 19:13:23 -07001337 }
1338
1339 @Override
1340 public void writeToParcel(Parcel out, int flags) {
1341 super.writeToParcel(out, flags);
1342 out.writeInt(this.transportState);
Michael Jurka14138892012-11-07 13:45:53 -08001343 out.writeInt(this.appWidgetToShow);
Jim Miller223ce5c2012-10-05 19:13:23 -07001344 }
1345
1346 public static final Parcelable.Creator<SavedState> CREATOR
1347 = new Parcelable.Creator<SavedState>() {
1348 public SavedState createFromParcel(Parcel in) {
1349 return new SavedState(in);
1350 }
1351
1352 public SavedState[] newArray(int size) {
1353 return new SavedState[size];
1354 }
1355 };
1356 }
1357
1358 @Override
1359 public Parcelable onSaveInstanceState() {
Jim Miller4894a012013-04-03 15:23:55 -07001360 if (DEBUG) Log.d(TAG, "onSaveInstanceState, tstate=" + mTransportState);
Jim Miller223ce5c2012-10-05 19:13:23 -07001361 Parcelable superState = super.onSaveInstanceState();
1362 SavedState ss = new SavedState(superState);
Jim Miller4894a012013-04-03 15:23:55 -07001363 // If the transport is showing, force it to show it on restore.
1364 final boolean showing = mTransportControl != null
1365 && mAppWidgetContainer.getWidgetPageIndex(mTransportControl) >= 0;
1366 ss.transportState = showing ? TRANSPORT_VISIBLE : mTransportState;
Michael Jurka14138892012-11-07 13:45:53 -08001367 ss.appWidgetToShow = mAppWidgetToShow;
Jim Miller223ce5c2012-10-05 19:13:23 -07001368 return ss;
1369 }
1370
1371 @Override
1372 public void onRestoreInstanceState(Parcelable state) {
1373 if (!(state instanceof SavedState)) {
1374 super.onRestoreInstanceState(state);
1375 return;
1376 }
1377 SavedState ss = (SavedState) state;
1378 super.onRestoreInstanceState(ss.getSuperState());
Jim Miller8f09fd22013-03-14 19:04:28 -07001379 mTransportState = (ss.transportState);
Michael Jurka14138892012-11-07 13:45:53 -08001380 mAppWidgetToShow = ss.appWidgetToShow;
Jim Miller4894a012013-04-03 15:23:55 -07001381 if (DEBUG) Log.d(TAG, "onRestoreInstanceState, transport=" + mTransportState);
Winson Chung0db59a82012-12-05 15:58:43 -08001382 post(mSwitchPageRunnable);
Jim Miller223ce5c2012-10-05 19:13:23 -07001383 }
1384
John Spurlock5f050e52012-10-27 10:44:19 -04001385 @Override
1386 public void onWindowFocusChanged(boolean hasWindowFocus) {
1387 super.onWindowFocusChanged(hasWindowFocus);
1388 if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
Michael Jurka76017ca2012-11-06 16:21:09 -08001389 if (hasWindowFocus && mShowSecurityWhenReturn) {
Jim Milleraaf9b112012-10-31 19:44:56 -07001390 SlidingChallengeLayout slider =
1391 (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
1392 if (slider != null) {
1393 slider.setHandleAlpha(1);
1394 slider.showChallenge(true);
1395 }
1396 mShowSecurityWhenReturn = false;
John Spurlock5f050e52012-10-27 10:44:19 -04001397 }
1398 }
1399
Jim Miller223ce5c2012-10-05 19:13:23 -07001400 private void showAppropriateWidgetPage() {
Jim Miller8f09fd22013-03-14 19:04:28 -07001401 int state = mTransportState;
1402 ensureTransportPresentOrRemoved(state);
1403 int pageToShow = getAppropriateWidgetPage(state);
Jim Miller223ce5c2012-10-05 19:13:23 -07001404 mAppWidgetContainer.setCurrentPage(pageToShow);
Jim Millerdcb3d842012-08-23 19:18:12 -07001405 }
1406
Jim Miller4894a012013-04-03 15:23:55 -07001407 /**
1408 * Examines the current state and adds the transport to the widget pager when the state changes.
1409 *
1410 * Showing the initial transport and keeping it around is a bit tricky because the signals
1411 * coming from music players aren't always clear. Here's how the states are handled:
1412 *
1413 * {@link TRANSPORT_GONE} means we have no reason to show the transport - remove it if present.
1414 *
1415 * {@link TRANSPORT_INVISIBLE} means we have potential to show the transport because a music
1416 * player is registered but not currently playing music (or we don't know the state yet). The
1417 * code adds it conditionally on play state.
1418 *
1419 * {@link #TRANSPORT_VISIBLE} means a music player is active and transport should be showing.
1420 *
1421 * Once the transport is showing, we always show it until keyguard is dismissed. This state is
1422 * maintained by onSave/RestoreInstanceState(). This state is cleared in
1423 * {@link KeyguardViewManager#hide} when keyguard is dismissed, which causes the transport to be
1424 * gone when keyguard is restarted until we get an update with the current state.
1425 *
1426 * @param state
1427 */
Jim Miller8f09fd22013-03-14 19:04:28 -07001428 private void ensureTransportPresentOrRemoved(int state) {
Jim Miller4894a012013-04-03 15:23:55 -07001429 final boolean showing = getWidgetPosition(R.id.keyguard_transport_control) != -1;
1430 final boolean visible = state == TRANSPORT_VISIBLE;
1431 final boolean shouldBeVisible = state == TRANSPORT_INVISIBLE && isMusicPlaying(state);
1432 if (!showing && (visible || shouldBeVisible)) {
1433 if (DEBUGXPORT) Log.v(TAG, "add transport");
1434 // insert to left of camera if it exists, otherwise after right-most widget
1435 int lastWidget = mAppWidgetContainer.getChildCount() - 1;
1436 int position = 0; // handle no widget case
1437 if (lastWidget >= 0) {
1438 position = mAppWidgetContainer.isCameraPage(lastWidget) ?
1439 lastWidget : lastWidget + 1;
Jim Miller8f09fd22013-03-14 19:04:28 -07001440 }
Jim Miller4894a012013-04-03 15:23:55 -07001441 mAppWidgetContainer.addWidget(getOrCreateTransportControl(), position);
1442 } else if (showing && state == TRANSPORT_GONE) {
Jim Miller8f09fd22013-03-14 19:04:28 -07001443 if (DEBUGXPORT) Log.v(TAG, "remove transport");
Jim Miller4894a012013-04-03 15:23:55 -07001444 mAppWidgetContainer.removeWidget(getOrCreateTransportControl());
Jim Miller8f09fd22013-03-14 19:04:28 -07001445 mTransportControl = null;
1446 }
1447 }
1448
John Spurlockdbe24b72012-11-01 13:01:05 -04001449 private CameraWidgetFrame findCameraPage() {
1450 for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
Winson Chung6cf53bb2012-11-05 17:55:42 -08001451 if (mAppWidgetContainer.isCameraPage(i)) {
John Spurlockdbe24b72012-11-01 13:01:05 -04001452 return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
1453 }
1454 }
1455 return null;
1456 }
1457
Winson Chung6cf53bb2012-11-05 17:55:42 -08001458 boolean isMusicPage(int pageIndex) {
1459 return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
1460 }
1461
Jim Miller8f09fd22013-03-14 19:04:28 -07001462 private int getAppropriateWidgetPage(int musicTransportState) {
John Spurlock358148e2012-10-26 15:29:59 -04001463 // assumes at least one widget (besides camera + add)
Michael Jurka76017ca2012-11-06 16:21:09 -08001464 if (mAppWidgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
1465 final int childCount = mAppWidgetContainer.getChildCount();
1466 for (int i = 0; i < childCount; i++) {
1467 if (mAppWidgetContainer.getWidgetPageAt(i).getContentAppWidgetId()
1468 == mAppWidgetToShow) {
Michael Jurka76017ca2012-11-06 16:21:09 -08001469 return i;
1470 }
1471 }
1472 mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1473 }
John Spurlock358148e2012-10-26 15:29:59 -04001474 // if music playing, show transport
Jim Miller8f09fd22013-03-14 19:04:28 -07001475 if (musicTransportState == TRANSPORT_VISIBLE) {
John Spurlock358148e2012-10-26 15:29:59 -04001476 if (DEBUG) Log.d(TAG, "Music playing, show transport");
Jim Miller4894a012013-04-03 15:23:55 -07001477 return mAppWidgetContainer.getWidgetPageIndex(getOrCreateTransportControl());
John Spurlock358148e2012-10-26 15:29:59 -04001478 }
1479
John Spurlock5f050e52012-10-27 10:44:19 -04001480 // else show the right-most widget (except for camera)
John Spurlock358148e2012-10-26 15:29:59 -04001481 int rightMost = mAppWidgetContainer.getChildCount() - 1;
Winson Chung6cf53bb2012-11-05 17:55:42 -08001482 if (mAppWidgetContainer.isCameraPage(rightMost)) {
John Spurlock358148e2012-10-26 15:29:59 -04001483 rightMost--;
1484 }
John Spurlock5f050e52012-10-27 10:44:19 -04001485 if (DEBUG) Log.d(TAG, "Show right-most page " + rightMost);
John Spurlock358148e2012-10-26 15:29:59 -04001486 return rightMost;
1487 }
1488
Jim Miller19a52672012-10-23 19:52:04 -07001489 private void enableUserSelectorIfNecessary() {
Jim Miller26e6c2e2012-10-30 14:12:22 -07001490 if (!UserManager.supportsMultipleUsers()) {
1491 return; // device doesn't support multi-user mode
1492 }
Jim Millerf6ab5f92012-11-07 16:15:13 -08001493 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Chris Wrend2dec002012-11-07 16:38:33 -05001494 if (um == null) {
1495 Throwable t = new Throwable();
1496 t.fillInStackTrace();
1497 Log.e(TAG, "user service is null.", t);
1498 return;
1499 }
Jim Miller26e6c2e2012-10-30 14:12:22 -07001500
John Spurlock5f050e52012-10-27 10:44:19 -04001501 // if there are multiple users, we need to enable to multi-user switcher
Jim Millerf6ab5f92012-11-07 16:15:13 -08001502 final List<UserInfo> users = um.getUsers(true);
Chris Wrend2dec002012-11-07 16:38:33 -05001503 if (users == null) {
1504 Throwable t = new Throwable();
1505 t.fillInStackTrace();
1506 Log.e(TAG, "list of users is null.", t);
1507 return;
1508 }
Adam Cohen66b9fb1662012-09-05 16:23:58 -07001509
Jim Millerf6ab5f92012-11-07 16:15:13 -08001510 final View multiUserView = findViewById(R.id.keyguard_user_selector);
1511 if (multiUserView == null) {
1512 Throwable t = new Throwable();
1513 t.fillInStackTrace();
1514 Log.e(TAG, "can't find user_selector in layout.", t);
1515 return;
1516 }
1517
Chris Wrend2dec002012-11-07 16:38:33 -05001518 if (users.size() > 1) {
Chris Wren91f080c2012-11-07 15:20:27 -05001519 if (multiUserView instanceof KeyguardMultiUserSelectorView) {
Chris Wrenf41c61b2012-11-29 15:19:54 -05001520 mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
1521 mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
1522 mKeyguardMultiUserSelectorView.addUsers(users);
Chris Wren91f080c2012-11-07 15:20:27 -05001523 UserSwitcherCallback callback = new UserSwitcherCallback() {
1524 @Override
1525 public void hideSecurityView(int duration) {
1526 mSecurityViewContainer.animate().alpha(0).setDuration(duration);
Jim Miller0ff7f012012-10-11 20:40:01 -07001527 }
Adam Cohen0a8d3262012-10-03 13:50:55 -07001528
Chris Wren91f080c2012-11-07 15:20:27 -05001529 @Override
1530 public void showSecurityView() {
1531 mSecurityViewContainer.setAlpha(1.0f);
Jim Miller19a52672012-10-23 19:52:04 -07001532 }
Chris Wren91f080c2012-11-07 15:20:27 -05001533
1534 @Override
1535 public void showUnlockHint() {
1536 if (mKeyguardSelectorView != null) {
1537 mKeyguardSelectorView.showUsabilityHint();
1538 }
1539 }
1540
1541 @Override
1542 public void userActivity() {
1543 if (mViewMediatorCallback != null) {
1544 mViewMediatorCallback.userActivity();
1545 }
1546 }
1547 };
Chris Wrenf41c61b2012-11-29 15:19:54 -05001548 mKeyguardMultiUserSelectorView.setCallback(callback);
Chris Wrend2dec002012-11-07 16:38:33 -05001549 } else {
1550 Throwable t = new Throwable();
1551 t.fillInStackTrace();
1552 if (multiUserView == null) {
1553 Log.e(TAG, "could not find the user_selector.", t);
1554 } else {
1555 Log.e(TAG, "user_selector is the wrong type.", t);
1556 }
Chris Wren91f080c2012-11-07 15:20:27 -05001557 }
Adam Cohen66b9fb1662012-09-05 16:23:58 -07001558 }
1559 }
1560
Jim Millerdcb3d842012-08-23 19:18:12 -07001561 @Override
1562 public void cleanUp() {
Adam Cohen128f2762013-04-18 13:37:05 -07001563 // Make sure we let go of all widgets and their package contexts promptly. If we don't do
1564 // this, and the associated application is uninstalled, it can cause a soft reboot.
1565 int count = mAppWidgetContainer.getChildCount();
1566 for (int i = 0; i < count; i++) {
1567 KeyguardWidgetFrame frame = mAppWidgetContainer.getWidgetPageAt(i);
1568 frame.removeAllViews();
1569 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001570 }
1571
Jim Miller95b005c2012-08-29 16:43:32 -07001572 /**
1573 * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
1574 * some cases where we wish to disable it, notably when the menu button placement or technology
1575 * is prone to false positives.
1576 *
1577 * @return true if the menu key should be enabled
1578 */
1579 private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
1580 private boolean shouldEnableMenuKey() {
1581 final Resources res = getResources();
Jim Miller5ecd8112013-01-09 18:50:26 -08001582 final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
Jim Miller95b005c2012-08-29 16:43:32 -07001583 final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
1584 final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
1585 return !configDisabled || isTestHarness || fileOverride;
1586 }
1587
Michael Jurka76017ca2012-11-06 16:21:09 -08001588 public void goToWidget(int appWidgetId) {
1589 mAppWidgetToShow = appWidgetId;
1590 mSwitchPageRunnable.run();
1591 }
1592
Jim Miller75931e02012-11-02 16:39:22 -07001593 public boolean handleMenuKey() {
1594 // The following enables the MENU key to work for testing automation
1595 if (shouldEnableMenuKey()) {
1596 showNextSecurityScreenOrFinish(false);
1597 return true;
1598 }
1599 return false;
1600 }
1601
Jim Miller0a34d9e2012-10-05 17:15:41 -07001602 public boolean handleBackKey() {
John Spurlock03eca852013-03-14 14:21:04 -04001603 if (mCurrentSecuritySelection == SecurityMode.Account) {
1604 // go back to primary screen and re-disable back
1605 setBackButtonEnabled(false);
1606 showPrimarySecurityScreen(false /*turningOff*/);
1607 return true;
1608 }
Jim Miller0a34d9e2012-10-05 17:15:41 -07001609 if (mCurrentSecuritySelection != SecurityMode.None) {
1610 mCallback.dismiss(false);
1611 return true;
1612 }
1613 return false;
1614 }
1615
Craig Mautnerad09bcc2012-10-08 13:33:11 -07001616 /**
1617 * Dismisses the keyguard by going to the next screen or making it gone.
1618 */
1619 public void dismiss() {
1620 showNextSecurityScreenOrFinish(false);
1621 }
Jim Miller4eeb4f62012-11-08 00:04:29 -08001622
1623 public void showAssistant() {
1624 final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
Dianne Hackbornf9c5e0f2013-01-23 14:39:13 -08001625 .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
Jim Miller4eeb4f62012-11-08 00:04:29 -08001626
1627 if (intent == null) return;
1628
1629 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
1630 R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
1631 getHandler(), null);
1632
1633 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jim Miller4eeb4f62012-11-08 00:04:29 -08001634
Daniel Sandler6ed3fca2012-11-08 09:58:27 -05001635 mActivityLauncher.launchActivityWithAnimation(
1636 intent, false, opts.toBundle(), null, null);
Jim Miller4eeb4f62012-11-08 00:04:29 -08001637 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001638}