blob: 7ac94bd4a135ea513aafa15c336c99aea9194b04 [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
Andres Morales38a7ed02013-11-14 19:02:56 -080019import android.nfc.NfcUnlock;
Jim Miller3eb49712014-01-28 18:22:42 -080020
Jim Miller4d20ed32013-10-19 01:00:16 +000021import com.android.internal.widget.LockPatternUtils;
22import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
23import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
24
Jim Miller258341c2012-08-30 16:50:10 -070025import android.app.Activity;
Jim Miller95b005c2012-08-29 16:43:32 -070026import android.app.ActivityManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070027import android.app.ActivityOptions;
Jim Miller4eeb4f62012-11-08 00:04:29 -080028import android.app.SearchManager;
Jim Miller258341c2012-08-30 16:50:10 -070029import android.app.admin.DevicePolicyManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070030import android.appwidget.AppWidgetHost;
31import android.appwidget.AppWidgetHostView;
32import android.appwidget.AppWidgetManager;
33import android.appwidget.AppWidgetProviderInfo;
Michael Jurkafc753c02012-10-30 18:30:52 -070034import android.content.ComponentName;
Jim Millerdcb3d842012-08-23 19:18:12 -070035import android.content.Context;
36import android.content.Intent;
37import android.content.IntentSender;
Jim Millera75a8832013-02-07 16:53:32 -080038import android.content.pm.PackageManager.NameNotFoundException;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070039import android.content.pm.UserInfo;
Jim Miller95b005c2012-08-29 16:43:32 -070040import android.content.res.Resources;
Jim Miller57375342012-09-09 15:20:31 -070041import android.graphics.Rect;
Jim Miller8f09fd22013-03-14 19:04:28 -070042import android.media.RemoteControlClient;
Jim Miller5e612cf2014-02-03 17:57:23 -080043import android.os.Bundle;
Jim Millerf229e4d2012-09-12 20:32:50 -070044import android.os.Looper;
Jim Miller223ce5c2012-10-05 19:13:23 -070045import android.os.Parcel;
46import android.os.Parcelable;
John Spurlockdbe24b72012-11-01 13:01:05 -040047import android.os.SystemClock;
Jim Miller4eeb4f62012-11-08 00:04:29 -080048import android.os.UserHandle;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070049import android.os.UserManager;
Michael Jurkafff56142012-11-28 16:51:00 -080050import android.provider.Settings;
Jim Millerdcb3d842012-08-23 19:18:12 -070051import android.util.AttributeSet;
52import android.util.Log;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070053import android.view.LayoutInflater;
Jim Miller57375342012-09-09 15:20:31 -070054import android.view.MotionEvent;
Jim Millerdcb3d842012-08-23 19:18:12 -070055import android.view.View;
Jim Millerdcb3d842012-08-23 19:18:12 -070056import android.widget.RemoteViews.OnClickHandler;
57
Jim Miller95b005c2012-08-29 16:43:32 -070058import java.io.File;
Chet Haase7fc27ea2013-10-01 15:34:22 -070059import java.lang.ref.WeakReference;
Adam Cohen66b9fb1662012-09-05 16:23:58 -070060import java.util.List;
Jim Millerdcb3d842012-08-23 19:18:12 -070061
62public class KeyguardHostView extends KeyguardViewBase {
Jim Miller51117262012-11-04 17:58:09 -080063 private static final String TAG = "KeyguardHostView";
Jim Miller3eb49712014-01-28 18:22:42 -080064 public static boolean DEBUG = KeyguardViewMediator.DEBUG;
65 public static boolean DEBUGXPORT = true; // debug music transport control
Sandeep Siddharthaeec83dc2013-09-04 14:59:59 -070066
Jim Miller4894a012013-04-03 15:23:55 -070067 // Transport control states.
Jim Miller8f09fd22013-03-14 19:04:28 -070068 static final int TRANSPORT_GONE = 0;
69 static final int TRANSPORT_INVISIBLE = 1;
70 static final int TRANSPORT_VISIBLE = 2;
71
72 private int mTransportState = TRANSPORT_GONE;
Jim Millerff2aa0b2012-09-06 19:03:52 -070073
Michael Jurka192d6d42012-11-07 01:09:38 -080074 // Found in KeyguardAppWidgetPickActivity.java
Jim Millerdcb3d842012-08-23 19:18:12 -070075 static final int APPWIDGET_HOST_ID = 0x4B455947;
Michael Jurkaeb963f02012-11-08 00:32:29 -080076 private final int MAX_WIDGETS = 5;
77
Jim Millerdcb3d842012-08-23 19:18:12 -070078 private AppWidgetHost mAppWidgetHost;
Michael Jurka67a871d2012-11-01 18:26:01 -070079 private AppWidgetManager mAppWidgetManager;
Jim Millerf2dfc352012-08-29 18:42:21 -070080 private KeyguardWidgetPager mAppWidgetContainer;
Jim Miller4e81bd42012-10-01 20:21:02 -070081 private KeyguardTransportControlView mTransportControl;
Michael Jurka76017ca2012-11-06 16:21:09 -080082 private int mAppWidgetToShow;
Jim Millerdcb3d842012-08-23 19:18:12 -070083
Jim Millerdcb3d842012-08-23 19:18:12 -070084 protected int mFailedAttempts;
Jim Millerdcb3d842012-08-23 19:18:12 -070085
Jim Millerd6523da2012-10-21 16:47:02 -070086 private KeyguardViewStateManager mViewStateManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070087
Jim Miller57375342012-09-09 15:20:31 -070088 private Rect mTempRect = new Rect();
Jim Miller51117262012-11-04 17:58:09 -080089 private int mDisabledFeatures;
Jim Miller51117262012-11-04 17:58:09 -080090 private boolean mCameraDisabled;
Jim Miller51117262012-11-04 17:58:09 -080091 private boolean mSafeModeEnabled;
Michael Jurkafff56142012-11-28 16:51:00 -080092 private boolean mUserSetupCompleted;
Chris Wrenf41c61b2012-11-29 15:19:54 -050093
Jim Millera75a8832013-02-07 16:53:32 -080094 // User for whom this host view was created. Final because we should never change the
95 // id without reconstructing an instance of KeyguardHostView. See note below...
96 private final int mUserId;
Michael Jurkafff56142012-11-28 16:51:00 -080097
Chris Wrenf41c61b2012-11-29 15:19:54 -050098 private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
99
Jim Miller8f09fd22013-03-14 19:04:28 -0700100 protected int mClientGeneration;
Jim Miller57375342012-09-09 15:20:31 -0700101
Jim Millere51cf7ae2013-06-25 18:31:56 -0700102 protected boolean mShowSecurityWhenReturn;
103
John Spurlock256ae672013-09-26 12:14:33 -0400104 private final Rect mInsets = new Rect();
105
Chet Haase7fc27ea2013-10-01 15:34:22 -0700106 private MyOnClickHandler mOnClickHandler = new MyOnClickHandler(this);
107
Jim Miller9ccf1232013-10-10 22:23:07 -0700108 private Runnable mPostBootCompletedRunnable;
109
Adam Cohen24b351a2012-09-14 15:02:27 -0700110 /*package*/ interface UserSwitcherCallback {
111 void hideSecurityView(int duration);
112 void showSecurityView();
Adam Cohen0a8d3262012-10-03 13:50:55 -0700113 void showUnlockHint();
Jim Miller19a52672012-10-23 19:52:04 -0700114 void userActivity();
Adam Cohen24b351a2012-09-14 15:02:27 -0700115 }
116
Adam Powellf8895242013-09-30 16:16:24 -0700117 interface TransportControlCallback {
118 void userActivity();
119 }
120
John Spurlock14adfe42012-11-08 10:29:26 -0500121 /*package*/ interface OnDismissAction {
122 /* returns true if the dismiss should be deferred */
123 boolean onDismiss();
124 }
125
Jim Millerdcb3d842012-08-23 19:18:12 -0700126 public KeyguardHostView(Context context) {
127 this(context, null);
128 }
129
130 public KeyguardHostView(Context context, AttributeSet attrs) {
131 super(context, attrs);
Jim Miller4894a012013-04-03 15:23:55 -0700132
133 if (DEBUG) Log.e(TAG, "KeyguardHostView()");
134
Jim Miller000464a2012-09-04 16:45:06 -0700135 mLockPatternUtils = new LockPatternUtils(context);
Jim Millera75a8832013-02-07 16:53:32 -0800136
137 // Note: This depends on KeyguardHostView getting reconstructed every time the
138 // user switches, since mUserId will be used for the entire session.
139 // Once created, keyguard should *never* re-use this instance with another user.
140 // In other words, mUserId should never change - hence it's marked final.
Amith Yamasanic566b432012-11-30 15:26:21 -0800141 mUserId = mLockPatternUtils.getCurrentUser();
Jim Millera75a8832013-02-07 16:53:32 -0800142
Jim Miller105bedd2013-02-27 21:35:18 -0800143 DevicePolicyManager dpm =
144 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
145 if (dpm != null) {
146 mDisabledFeatures = getDisabledFeatures(dpm);
147 mCameraDisabled = dpm.getCameraDisabled(null);
148 }
149
150 mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
151
152 // These need to be created with the user context...
Jim Millera75a8832013-02-07 16:53:32 -0800153 Context userContext = null;
154 try {
155 final String packageName = "system";
156 userContext = mContext.createPackageContextAsUser(packageName, 0,
157 new UserHandle(mUserId));
158
159 } catch (NameNotFoundException e) {
160 e.printStackTrace();
161 // This should never happen, but it's better to have no widgets than to crash.
162 userContext = context;
163 }
164
Jim Millera75a8832013-02-07 16:53:32 -0800165 mAppWidgetHost = new AppWidgetHost(userContext, APPWIDGET_HOST_ID, mOnClickHandler,
166 Looper.myLooper());
Jim Miller105bedd2013-02-27 21:35:18 -0800167
Jim Millera75a8832013-02-07 16:53:32 -0800168 mAppWidgetManager = AppWidgetManager.getInstance(userContext);
169
Adam Cohend6f89602012-11-06 11:46:25 -0800170 mViewStateManager = new KeyguardViewStateManager(this);
Jim Miller51117262012-11-04 17:58:09 -0800171
Michael Jurkafff56142012-11-28 16:51:00 -0800172 mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
173 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
Jim Miller51117262012-11-04 17:58:09 -0800174
Jim Miller8f09fd22013-03-14 19:04:28 -0700175 // Ensure we have the current state *before* we call showAppropriateWidgetPage()
176 getInitialTransportState();
177
Jim Miller51117262012-11-04 17:58:09 -0800178 if (mSafeModeEnabled) {
179 Log.v(TAG, "Keyguard widgets disabled by safe mode");
180 }
181 if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
182 Log.v(TAG, "Keyguard widgets disabled by DPM");
183 }
184 if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
185 Log.v(TAG, "Keyguard secure camera disabled by DPM");
186 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700187 }
188
Jim Miller8f09fd22013-03-14 19:04:28 -0700189 private void getInitialTransportState() {
190 DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext)
191 .getCachedDisplayClientState();
192 mTransportState = (dcs.clearing ? TRANSPORT_GONE :
193 (isMusicPlaying(dcs.playbackState) ? TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
Jim Miller4894a012013-04-03 15:23:55 -0700194
Jim Miller81190be2013-11-05 18:17:59 -0800195 if (DEBUGXPORT) Log.v(TAG, "Initial transport state: "
Jim Millerdfb57cd2013-05-30 16:43:53 -0700196 + mTransportState + ", pbstate=" + dcs.playbackState);
Jim Miller8f09fd22013-03-14 19:04:28 -0700197 }
198
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800199 private void cleanupAppWidgetIds() {
Jim Miller9ccf1232013-10-10 22:23:07 -0700200 if (mSafeModeEnabled || widgetsDisabled()) return;
201
202 // Clean up appWidgetIds that are bound to lockscreen, but not actually used
203 // This is only to clean up after another bug: we used to not call
204 // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
205 // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
206 // that are triggered by deleteAppWidgetId, which is why we're doing this
207 int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
208 int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
209 for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
210 int appWidgetId = appWidgetIdsBoundToHost[i];
211 if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
212 Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
213 + appWidgetId);
214 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800215 }
216 }
217 }
218
219 private static boolean contains(int[] array, int target) {
220 for (int value : array) {
221 if (value == target) {
222 return true;
223 }
224 }
225 return false;
226 }
227
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800228 private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
229 new KeyguardUpdateMonitorCallback() {
230 @Override
231 public void onBootCompleted() {
Jim Miller9ccf1232013-10-10 22:23:07 -0700232 if (mPostBootCompletedRunnable != null) {
233 mPostBootCompletedRunnable.run();
234 mPostBootCompletedRunnable = null;
Michael Jurka545043e2012-11-21 14:02:34 -0800235 }
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800236 }
Chris Wrenf41c61b2012-11-29 15:19:54 -0500237 @Override
238 public void onUserSwitchComplete(int userId) {
239 if (mKeyguardMultiUserSelectorView != null) {
240 mKeyguardMultiUserSelectorView.finalizeActiveUserView(true);
241 }
242 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700243 @Override
244 void onMusicClientIdChanged(
245 int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
246 // Set transport state to invisible until we know music is playing (below)
247 if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
248 Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration);
249 }
250 mClientGeneration = clientGeneration;
Jim Millerdfb57cd2013-05-30 16:43:53 -0700251 final int newState = (clearing ? TRANSPORT_GONE
252 : (mTransportState == TRANSPORT_VISIBLE ?
253 TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
254 if (newState != mTransportState) {
255 mTransportState = newState;
256 if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
Jim Miller4d20ed32013-10-19 01:00:16 +0000257 KeyguardHostView.this.post(mSwitchPageRunnable);
Jim Millerdfb57cd2013-05-30 16:43:53 -0700258 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700259 }
260 @Override
261 public void onMusicPlaybackStateChanged(int playbackState, long eventTime) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700262 if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState);
263 if (mTransportState != TRANSPORT_GONE) {
Jim Millerdfb57cd2013-05-30 16:43:53 -0700264 final int newState = (isMusicPlaying(playbackState) ?
Jim Miller8f09fd22013-03-14 19:04:28 -0700265 TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE);
Jim Millerdfb57cd2013-05-30 16:43:53 -0700266 if (newState != mTransportState) {
267 mTransportState = newState;
268 if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
Jim Miller4d20ed32013-10-19 01:00:16 +0000269 KeyguardHostView.this.post(mSwitchPageRunnable);
Jim Millerdfb57cd2013-05-30 16:43:53 -0700270 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700271 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700272 }
Andres Morales38a7ed02013-11-14 19:02:56 -0800273 @Override
274 public void onNfcUnlock() {
Jim Miller7751ff62014-01-14 18:57:03 -0800275 if (NfcUnlock.getPropertyEnabled()) {
276 dismiss(true);
277 }
Andres Morales38a7ed02013-11-14 19:02:56 -0800278 }
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800279 };
280
Jim Miller8f09fd22013-03-14 19:04:28 -0700281 private static final boolean isMusicPlaying(int playbackState) {
282 // This should agree with the list in AudioService.isPlaystateActive()
283 switch (playbackState) {
284 case RemoteControlClient.PLAYSTATE_PLAYING:
285 case RemoteControlClient.PLAYSTATE_BUFFERING:
286 case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
287 case RemoteControlClient.PLAYSTATE_REWINDING:
288 case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
289 case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
290 return true;
291 default:
292 return false;
293 }
294 }
295
Jim Miller2cacda52012-11-07 22:40:20 -0800296 private SlidingChallengeLayout mSlidingChallengeLayout;
John Spurlock257f2832013-09-21 18:41:53 -0400297 private MultiPaneChallengeLayout mMultiPaneChallengeLayout;
Jim Miller2cacda52012-11-07 22:40:20 -0800298
Jim Millerdcb3d842012-08-23 19:18:12 -0700299 @Override
Jim Millerd2b82f72012-09-18 20:52:55 -0700300 public boolean onTouchEvent(MotionEvent ev) {
301 boolean result = super.onTouchEvent(ev);
Jim Miller57375342012-09-09 15:20:31 -0700302 mTempRect.set(0, 0, 0, 0);
Jim Miller3eb49712014-01-28 18:22:42 -0800303 offsetRectIntoDescendantCoords(getSecurityContainer(), mTempRect);
Jim Miller57375342012-09-09 15:20:31 -0700304 ev.offsetLocation(mTempRect.left, mTempRect.top);
Jim Miller3eb49712014-01-28 18:22:42 -0800305 result = getSecurityContainer().dispatchTouchEvent(ev) || result;
Jim Miller57375342012-09-09 15:20:31 -0700306 ev.offsetLocation(-mTempRect.left, -mTempRect.top);
307 return result;
308 }
309
Jim Millerff2aa0b2012-09-06 19:03:52 -0700310 private int getWidgetPosition(int id) {
Jim Miller982d21b2013-05-09 14:43:16 -0700311 final KeyguardWidgetPager appWidgetContainer = mAppWidgetContainer;
312 final int children = appWidgetContainer.getChildCount();
Jim Millerff2aa0b2012-09-06 19:03:52 -0700313 for (int i = 0; i < children; i++) {
Jim Miller982d21b2013-05-09 14:43:16 -0700314 final View content = appWidgetContainer.getWidgetPageAt(i).getContent();
315 if (content != null && content.getId() == id) {
Jim Millerff2aa0b2012-09-06 19:03:52 -0700316 return i;
Jim Miller982d21b2013-05-09 14:43:16 -0700317 } else if (content == null) {
318 // Attempt to track down bug #8886916
319 Log.w(TAG, "*** Null content at " + "i=" + i + ",id=" + id + ",N=" + children);
Jim Millerff2aa0b2012-09-06 19:03:52 -0700320 }
321 }
322 return -1;
323 }
324
Jim Millerdcb3d842012-08-23 19:18:12 -0700325 @Override
326 protected void onFinishInflate() {
Jim Miller3eb49712014-01-28 18:22:42 -0800327 super.onFinishInflate();
328
Jim Millerd6523da2012-10-21 16:47:02 -0700329 // Grab instances of and make any necessary changes to the main layouts. Create
330 // view state manager and wire up necessary listeners / callbacks.
Winson Chungf3b9ec82012-11-01 14:48:51 -0700331 View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
Jim Millerf2dfc352012-08-29 18:42:21 -0700332 mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
Jim Miller838906b2012-10-19 18:41:25 -0700333 mAppWidgetContainer.setVisibility(VISIBLE);
334 mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
Winson Chungf3b9ec82012-11-01 14:48:51 -0700335 mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
Jim Millerd6523da2012-10-21 16:47:02 -0700336 mAppWidgetContainer.setMinScale(0.5f);
337
Jim Miller2cacda52012-11-07 22:40:20 -0800338 mSlidingChallengeLayout = (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
339 if (mSlidingChallengeLayout != null) {
340 mSlidingChallengeLayout.setOnChallengeScrolledListener(mViewStateManager);
Jim Miller19a52672012-10-23 19:52:04 -0700341 }
Jim Millerd6523da2012-10-21 16:47:02 -0700342 mAppWidgetContainer.setViewStateManager(mViewStateManager);
Michael Jurka1254f2f2012-10-25 11:44:31 -0700343 mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
Jim Millerd6523da2012-10-21 16:47:02 -0700344
John Spurlock257f2832013-09-21 18:41:53 -0400345 mMultiPaneChallengeLayout =
346 (MultiPaneChallengeLayout) findViewById(R.id.multi_pane_challenge);
Jim Miller2cacda52012-11-07 22:40:20 -0800347 ChallengeLayout challenge = mSlidingChallengeLayout != null ? mSlidingChallengeLayout :
John Spurlock257f2832013-09-21 18:41:53 -0400348 mMultiPaneChallengeLayout;
Winson Chung48275d22012-11-05 10:56:31 -0800349 challenge.setOnBouncerStateChangedListener(mViewStateManager);
Winson Chung70c2f872012-11-07 21:47:12 -0800350 mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
Jim Millerd6523da2012-10-21 16:47:02 -0700351 mViewStateManager.setPagedView(mAppWidgetContainer);
Winson Chung48275d22012-11-05 10:56:31 -0800352 mViewStateManager.setChallengeLayout(challenge);
Jim Miller7751ff62014-01-14 18:57:03 -0800353
Jim Miller3eb49712014-01-28 18:22:42 -0800354 mViewStateManager.setSecurityViewContainer(getSecurityContainer());
Jim Miller68c24892012-10-14 05:04:00 -0700355
Jim Miller9ccf1232013-10-10 22:23:07 -0700356 if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
357 updateAndAddWidgets();
358 } else {
359 // We can't add widgets until after boot completes because AppWidgetHost may try
360 // to contact the providers. Do it later.
361 mPostBootCompletedRunnable = new Runnable() {
362 @Override
363 public void run() {
364 updateAndAddWidgets();
365 }
366 };
Michael Jurkaeb963f02012-11-08 00:32:29 -0800367 }
Jim Miller9ccf1232013-10-10 22:23:07 -0700368
Jim Miller3eb49712014-01-28 18:22:42 -0800369 getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
Jim Miller9ccf1232013-10-10 22:23:07 -0700370 enableUserSelectorIfNecessary();
371 }
372
373 private void updateAndAddWidgets() {
374 cleanupAppWidgetIds();
375 addDefaultWidgets();
376 addWidgetsFromSettings();
377 maybeEnableAddButton();
Jim Miller51117262012-11-04 17:58:09 -0800378 checkAppWidgetConsistency();
Jim Miller5547b552013-10-07 19:20:56 -0700379
380 // Don't let the user drag the challenge down if widgets are disabled.
381 if (mSlidingChallengeLayout != null) {
382 mSlidingChallengeLayout.setEnableChallengeDragging(!widgetsDisabled());
383 }
384
Jim Miller9ccf1232013-10-10 22:23:07 -0700385 // Select the appropriate page
Jim Miller51117262012-11-04 17:58:09 -0800386 mSwitchPageRunnable.run();
Jim Miller9ccf1232013-10-10 22:23:07 -0700387
Adam Cohen45adaa72012-11-02 22:00:57 -0700388 // This needs to be called after the pages are all added.
389 mViewStateManager.showUsabilityHints();
Jim Miller9ccf1232013-10-10 22:23:07 -0700390 }
Adam Cohen45adaa72012-11-02 22:00:57 -0700391
Jim Miller9ccf1232013-10-10 22:23:07 -0700392 private void maybeEnableAddButton() {
393 if (!shouldEnableAddWidget()) {
394 mAppWidgetContainer.setAddWidgetEnabled(false);
395 }
Jim Millere46efc02012-09-07 16:43:51 -0700396 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700397
Michael Jurkafff56142012-11-28 16:51:00 -0800398 private boolean shouldEnableAddWidget() {
399 return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
400 }
401
Jim Miller3eb49712014-01-28 18:22:42 -0800402 @Override
Jim Millerba7d94b2014-02-05 17:30:50 -0800403 public boolean dismiss(boolean authenticated) {
Jim Miller3eb49712014-01-28 18:22:42 -0800404 boolean finished = super.dismiss(authenticated);
405 if (!finished) {
406 mViewStateManager.showBouncer(true);
407
408 // Enter full screen mode if we're in SIM or Account screen
409 SecurityMode securityMode = getSecurityContainer().getSecurityMode();
410 boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
411 boolean isSimOrAccount = securityMode == SecurityMode.SimPin
412 || securityMode == SecurityMode.SimPuk
413 || securityMode == SecurityMode.Account;
414 mAppWidgetContainer.setVisibility(
415 isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
416
417 // Don't show camera or search in navbar when SIM or Account screen is showing
418 setSystemUiVisibility(isSimOrAccount ?
419 (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
420 : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
421
422 if (mSlidingChallengeLayout != null) {
423 mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
424 }
425 }
426 return finished;
427 }
428
Jim Miller51117262012-11-04 17:58:09 -0800429 private int getDisabledFeatures(DevicePolicyManager dpm) {
430 int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
431 if (dpm != null) {
432 final int currentUser = mLockPatternUtils.getCurrentUser();
433 disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
434 }
435 return disabledFeatures;
436 }
437
Jim Millerf45bb402013-08-20 18:58:32 -0700438 private boolean widgetsDisabled() {
Jim Miller461b3452013-09-29 14:00:01 -0700439 boolean disabledByLowRamDevice = ActivityManager.isLowRamDeviceStatic();
Jim Millerf45bb402013-08-20 18:58:32 -0700440 boolean disabledByDpm =
441 (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0;
442 boolean disabledByUser = !mLockPatternUtils.getWidgetsEnabled();
Jim Miller461b3452013-09-29 14:00:01 -0700443 return disabledByLowRamDevice || disabledByDpm || disabledByUser;
Jim Miller51117262012-11-04 17:58:09 -0800444 }
445
446 private boolean cameraDisabledByDpm() {
447 return mCameraDisabled
448 || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
449 }
450
Jim Miller5e612cf2014-02-03 17:57:23 -0800451 @Override
452 protected void setLockPatternUtils(LockPatternUtils utils) {
453 super.setLockPatternUtils(utils);
Jim Miller3eb49712014-01-28 18:22:42 -0800454 getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
Jim Millerdcb3d842012-08-23 19:18:12 -0700455 }
456
457 @Override
458 protected void onAttachedToWindow() {
459 super.onAttachedToWindow();
Jim Millera75a8832013-02-07 16:53:32 -0800460 mAppWidgetHost.startListening();
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800461 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
Jim Miller7221d3a2012-10-05 14:34:47 -0700462 }
463
Jim Millerdcb3d842012-08-23 19:18:12 -0700464 @Override
465 protected void onDetachedFromWindow() {
466 super.onDetachedFromWindow();
Jim Millera75a8832013-02-07 16:53:32 -0800467 mAppWidgetHost.stopListening();
Adam Cohenefb3ffb2012-11-06 16:55:32 -0800468 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
Jim Millerdcb3d842012-08-23 19:18:12 -0700469 }
470
Jim Millerd6523da2012-10-21 16:47:02 -0700471 void addWidget(AppWidgetHostView view, int pageIndex) {
472 mAppWidgetContainer.addWidget(view, pageIndex);
Jim Millerdcb3d842012-08-23 19:18:12 -0700473 }
474
Jim Miller838906b2012-10-19 18:41:25 -0700475 private KeyguardWidgetPager.Callbacks mWidgetCallbacks
476 = new KeyguardWidgetPager.Callbacks() {
Jeff Brownc7505bc2012-10-05 21:58:15 -0700477 @Override
478 public void userActivity() {
Adam Cohen08c83ef2012-11-08 00:25:47 -0800479 KeyguardHostView.this.userActivity();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700480 }
481
482 @Override
483 public void onUserActivityTimeoutChanged() {
Adam Cohen08c83ef2012-11-08 00:25:47 -0800484 KeyguardHostView.this.onUserActivityTimeoutChanged();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700485 }
Michael Jurkaeb963f02012-11-08 00:32:29 -0800486
487 @Override
Winson Chung40f82112012-11-08 11:54:55 -0800488 public void onAddView(View v) {
Michael Jurkafff56142012-11-28 16:51:00 -0800489 if (!shouldEnableAddWidget()) {
Winson Chung4752e7d2012-11-20 17:06:04 -0800490 mAppWidgetContainer.setAddWidgetEnabled(false);
Winson Chung40f82112012-11-08 11:54:55 -0800491 }
Winson Chung4752e7d2012-11-20 17:06:04 -0800492 }
Winson Chung40f82112012-11-08 11:54:55 -0800493
494 @Override
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800495 public void onRemoveView(View v, boolean deletePermanently) {
Michael Jurka75b5cfb2012-11-15 18:22:47 -0800496 if (deletePermanently) {
497 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
498 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
499 appWidgetId != LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
500 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
501 }
502 }
Michael Jurkaeb963f02012-11-08 00:32:29 -0800503 }
Winson Chung4752e7d2012-11-20 17:06:04 -0800504
505 @Override
506 public void onRemoveViewAnimationCompleted() {
Michael Jurkafff56142012-11-28 16:51:00 -0800507 if (shouldEnableAddWidget()) {
Winson Chung4752e7d2012-11-20 17:06:04 -0800508 mAppWidgetContainer.setAddWidgetEnabled(true);
509 }
510 }
Jeff Brownc7505bc2012-10-05 21:58:15 -0700511 };
512
Jim Miller5e612cf2014-02-03 17:57:23 -0800513 @Override
514 public void onUserSwitching(boolean switching) {
Chris Wrenf41c61b2012-11-29 15:19:54 -0500515 if (!switching && mKeyguardMultiUserSelectorView != null) {
516 mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
517 }
518 }
519
Adam Cohen08c83ef2012-11-08 00:25:47 -0800520 public void userActivity() {
521 if (mViewMediatorCallback != null) {
522 mViewMediatorCallback.userActivity();
523 }
524 }
525
526 public void onUserActivityTimeoutChanged() {
527 if (mViewMediatorCallback != null) {
528 mViewMediatorCallback.onUserActivityTimeoutChanged();
529 }
530 }
531
Jeff Brownc7505bc2012-10-05 21:58:15 -0700532 @Override
533 public long getUserActivityTimeout() {
534 // Currently only considering user activity timeouts needed by widgets.
535 // Could also take into account longer timeouts for certain security views.
Jim Miller838906b2012-10-19 18:41:25 -0700536 if (mAppWidgetContainer != null) {
537 return mAppWidgetContainer.getUserActivityTimeout();
Jeff Brownc7505bc2012-10-05 21:58:15 -0700538 }
539 return -1;
540 }
541
Chet Haase7fc27ea2013-10-01 15:34:22 -0700542 private static class MyOnClickHandler extends OnClickHandler {
543
544 // weak reference to the hostView to avoid keeping a live reference
545 // due to Binder GC linkages to AppWidgetHost. By the same token,
546 // this click handler should not keep references to any large
547 // objects.
Jim Miller7751ff62014-01-14 18:57:03 -0800548 WeakReference<KeyguardHostView> mKeyguardHostView;
Chet Haase7fc27ea2013-10-01 15:34:22 -0700549
550 MyOnClickHandler(KeyguardHostView hostView) {
Jim Miller7751ff62014-01-14 18:57:03 -0800551 mKeyguardHostView = new WeakReference<KeyguardHostView>(hostView);
Chet Haase7fc27ea2013-10-01 15:34:22 -0700552 }
553
Jim Millerdcb3d842012-08-23 19:18:12 -0700554 @Override
555 public boolean onClickHandler(final View view,
556 final android.app.PendingIntent pendingIntent,
557 final Intent fillInIntent) {
Jim Miller7751ff62014-01-14 18:57:03 -0800558 KeyguardHostView hostView = mKeyguardHostView.get();
Chet Haase7fc27ea2013-10-01 15:34:22 -0700559 if (hostView == null) {
560 return false;
561 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700562 if (pendingIntent.isActivity()) {
Chet Haase7fc27ea2013-10-01 15:34:22 -0700563 hostView.setOnDismissAction(new OnDismissAction() {
John Spurlock34c4fe52012-11-07 10:12:29 -0500564 public boolean onDismiss() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700565 try {
Chet Haase7fc27ea2013-10-01 15:34:22 -0700566 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
567 Context context = view.getContext();
568 ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
569 0, 0,
570 view.getMeasuredWidth(), view.getMeasuredHeight());
571 context.startIntentSender(
572 pendingIntent.getIntentSender(), fillInIntent,
573 Intent.FLAG_ACTIVITY_NEW_TASK,
574 Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
John Spurlock34c4fe52012-11-07 10:12:29 -0500575 } catch (IntentSender.SendIntentException e) {
576 android.util.Log.e(TAG, "Cannot send pending intent: ", e);
577 } catch (Exception e) {
578 android.util.Log.e(TAG, "Cannot send pending intent due to " +
579 "unknown exception: ", e);
580 }
581 return false;
Jim Millerdcb3d842012-08-23 19:18:12 -0700582 }
Jim Miller5f75aa12012-08-29 15:10:34 -0700583 });
Jim Millerdcb3d842012-08-23 19:18:12 -0700584
Chet Haase7fc27ea2013-10-01 15:34:22 -0700585 if (hostView.mViewStateManager.isChallengeShowing()) {
586 hostView.mViewStateManager.showBouncer(true);
Jim Miller08898372012-11-04 19:08:40 -0800587 } else {
Jim Miller7751ff62014-01-14 18:57:03 -0800588 hostView.dismiss();
Jim Miller08898372012-11-04 19:08:40 -0800589 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700590 return true;
591 } else {
592 return super.onClickHandler(view, pendingIntent, fillInIntent);
593 }
594 };
595 };
596
Jim Millerdcb3d842012-08-23 19:18:12 -0700597 @Override
598 public void onScreenTurnedOn() {
Jim Miller3eb49712014-01-28 18:22:42 -0800599 super.onScreenTurnedOn();
Adam Cohen6fb841f2012-10-24 13:15:38 -0700600 if (mViewStateManager != null) {
601 mViewStateManager.showUsabilityHints();
602 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700603 }
604
605 @Override
606 public void onScreenTurnedOff() {
Jim Miller3eb49712014-01-28 18:22:42 -0800607 super.onScreenTurnedOff();
Michael Jurka14138892012-11-07 13:45:53 -0800608 // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
609 // turns off we reset that behavior
610 clearAppWidgetToShow();
Jim Miller9ccf1232013-10-10 22:23:07 -0700611 if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
612 checkAppWidgetConsistency();
613 }
John Spurlockdbe24b72012-11-01 13:01:05 -0400614 CameraWidgetFrame cameraPage = findCameraPage();
615 if (cameraPage != null) {
616 cameraPage.onScreenTurnedOff();
617 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700618 }
619
Michael Jurka14138892012-11-07 13:45:53 -0800620 public void clearAppWidgetToShow() {
621 mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
622 }
623
Jim Miller51117262012-11-04 17:58:09 -0800624 private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
Michael Jurka67a871d2012-11-01 18:26:01 -0700625 AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
Jim Miller99a3cae2012-09-17 20:53:51 -0700626 if (appWidgetInfo != null) {
Jim Millera75a8832013-02-07 16:53:32 -0800627 AppWidgetHostView view = mAppWidgetHost.createView(mContext, appId, appWidgetInfo);
Jim Millerd6523da2012-10-21 16:47:02 -0700628 addWidget(view, pageIndex);
Michael Jurka67a871d2012-11-01 18:26:01 -0700629 return true;
Jim Miller99a3cae2012-09-17 20:53:51 -0700630 } else {
Jim Miller51117262012-11-04 17:58:09 -0800631 if (updateDbIfFailed) {
Jim Millera75a8832013-02-07 16:53:32 -0800632 Log.w(TAG, "*** AppWidgetInfo for app widget id " + appId + " was null for user"
633 + mUserId + ", deleting");
Jim Miller51117262012-11-04 17:58:09 -0800634 mAppWidgetHost.deleteAppWidgetId(appId);
635 mLockPatternUtils.removeAppWidget(appId);
636 }
Michael Jurka67a871d2012-11-01 18:26:01 -0700637 return false;
Jim Miller99a3cae2012-09-17 20:53:51 -0700638 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700639 }
640
John Spurlockdcc96812012-10-25 14:35:19 -0400641 private final CameraWidgetFrame.Callbacks mCameraWidgetCallbacks =
642 new CameraWidgetFrame.Callbacks() {
643 @Override
644 public void onLaunchingCamera() {
John Spurlock57f928f2012-11-02 13:09:25 -0400645 setSliderHandleAlpha(0);
John Spurlockdcc96812012-10-25 14:35:19 -0400646 }
647
648 @Override
John Spurlock57f928f2012-11-02 13:09:25 -0400649 public void onCameraLaunchedSuccessfully() {
Winson Chung6cf53bb2012-11-05 17:55:42 -0800650 if (mAppWidgetContainer.isCameraPage(mAppWidgetContainer.getCurrentPage())) {
John Spurlock4b976ea2012-10-28 12:34:11 -0400651 mAppWidgetContainer.scrollLeft();
652 }
John Spurlock57f928f2012-11-02 13:09:25 -0400653 setSliderHandleAlpha(1);
Jim Milleraaf9b112012-10-31 19:44:56 -0700654 mShowSecurityWhenReturn = true;
John Spurlockdcc96812012-10-25 14:35:19 -0400655 }
656
John Spurlock57f928f2012-11-02 13:09:25 -0400657 @Override
658 public void onCameraLaunchedUnsuccessfully() {
659 setSliderHandleAlpha(1);
660 }
661
662 private void setSliderHandleAlpha(float alpha) {
663 SlidingChallengeLayout slider =
664 (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
665 if (slider != null) {
666 slider.setHandleAlpha(alpha);
667 }
John Spurlockdcc96812012-10-25 14:35:19 -0400668 }
669 };
670
Michael Jurkaeb963f02012-11-08 00:32:29 -0800671 private int numWidgets() {
672 final int childCount = mAppWidgetContainer.getChildCount();
673 int widgetCount = 0;
674 for (int i = 0; i < childCount; i++) {
675 if (mAppWidgetContainer.isWidgetPage(i)) {
676 widgetCount++;
677 }
678 }
679 return widgetCount;
680 }
681
Jim Miller4e81bd42012-10-01 20:21:02 -0700682 private void addDefaultWidgets() {
Jim Millerf45bb402013-08-20 18:58:32 -0700683 if (!mSafeModeEnabled && !widgetsDisabled()) {
Jim Miller8f09fd22013-03-14 19:04:28 -0700684 LayoutInflater inflater = LayoutInflater.from(mContext);
Jim Miller51117262012-11-04 17:58:09 -0800685 View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
Michael Jurkaeb963f02012-11-08 00:32:29 -0800686 mAppWidgetContainer.addWidget(addWidget, 0);
Jim Miller51117262012-11-04 17:58:09 -0800687 View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
688 addWidgetButton.setOnClickListener(new OnClickListener() {
689 @Override
690 public void onClick(View v) {
Michael Jurka192d6d42012-11-07 01:09:38 -0800691 // Pass in an invalid widget id... the picker will allocate an ID for us
Jim Miller3eb49712014-01-28 18:22:42 -0800692 getActivityLauncher().launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
Jim Miller51117262012-11-04 17:58:09 -0800693 }
694 });
695 }
696
697 // We currently disable cameras in safe mode because we support loading 3rd party
698 // cameras we can't trust. TODO: plumb safe mode into camera creation code and only
699 // inflate system-provided camera?
John Spurlock371f3402012-11-30 09:20:43 -0500700 if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
Jim Miller51117262012-11-04 17:58:09 -0800701 && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
Jim Miller3eb49712014-01-28 18:22:42 -0800702 View cameraWidget = CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks,
703 getActivityLauncher());
John Spurlockdcc96812012-10-25 14:35:19 -0400704 if (cameraWidget != null) {
705 mAppWidgetContainer.addWidget(cameraWidget);
706 }
John Spurlock86b63572012-10-24 11:24:25 -0400707 }
Jim Miller7221d3a2012-10-05 14:34:47 -0700708 }
709
Jim Miller8f09fd22013-03-14 19:04:28 -0700710 /**
711 * Create KeyguardTransportControlView on demand.
712 * @return
713 */
Jim Miller4894a012013-04-03 15:23:55 -0700714 private KeyguardTransportControlView getOrCreateTransportControl() {
Jim Miller8f09fd22013-03-14 19:04:28 -0700715 if (mTransportControl == null) {
716 LayoutInflater inflater = LayoutInflater.from(mContext);
717 mTransportControl = (KeyguardTransportControlView)
718 inflater.inflate(R.layout.keyguard_transport_control_view, this, false);
Adam Powellf8895242013-09-30 16:16:24 -0700719 mTransportControl.setTransportControlCallback(new TransportControlCallback() {
720 public void userActivity() {
721 mViewMediatorCallback.userActivity();
722 }
723 });
Jim Millerbdca3c02012-10-29 19:11:50 -0700724 }
Jim Miller8f09fd22013-03-14 19:04:28 -0700725 return mTransportControl;
Jim Miller4e81bd42012-10-01 20:21:02 -0700726 }
727
Jim Miller51117262012-11-04 17:58:09 -0800728 private int getInsertPageIndex() {
Michael Jurka67a871d2012-11-01 18:26:01 -0700729 View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
Jim Miller51117262012-11-04 17:58:09 -0800730 int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget);
731 if (insertionIndex < 0) {
732 insertionIndex = 0; // no add widget page found
733 } else {
734 insertionIndex++; // place after add widget
Michael Jurka67a871d2012-11-01 18:26:01 -0700735 }
Jim Miller51117262012-11-04 17:58:09 -0800736 return insertionIndex;
Michael Jurka67a871d2012-11-01 18:26:01 -0700737 }
738
739 private void addDefaultStatusWidget(int index) {
740 LayoutInflater inflater = LayoutInflater.from(mContext);
741 View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
742 mAppWidgetContainer.addWidget(statusWidget, index);
743 }
744
Michael Jurka1254f2f2012-10-25 11:44:31 -0700745 private void addWidgetsFromSettings() {
Jim Millerf45bb402013-08-20 18:58:32 -0700746 if (mSafeModeEnabled || widgetsDisabled()) {
Jim Miller2ec4ff42013-08-28 17:41:16 -0700747 addDefaultStatusWidget(0);
Jim Miller51117262012-11-04 17:58:09 -0800748 return;
Jim Millerb8ec4702012-08-31 17:19:10 -0700749 }
Jim Millerf229e4d2012-09-12 20:32:50 -0700750
Jim Miller51117262012-11-04 17:58:09 -0800751 int insertionIndex = getInsertPageIndex();
Michael Jurka20c41d52012-09-20 19:01:06 -0700752
753 // Add user-selected widget
Michael Jurkaaa2859a2012-10-24 12:46:49 -0700754 final int[] widgets = mLockPatternUtils.getAppWidgets();
Michael Jurka67a871d2012-11-01 18:26:01 -0700755
Michael Jurkaaa2859a2012-10-24 12:46:49 -0700756 if (widgets == null) {
757 Log.d(TAG, "Problem reading widgets");
758 } else {
759 for (int i = widgets.length -1; i >= 0; i--) {
Michael Jurka1254f2f2012-10-25 11:44:31 -0700760 if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
Jim Miller51117262012-11-04 17:58:09 -0800761 addDefaultStatusWidget(insertionIndex);
Michael Jurka1254f2f2012-10-25 11:44:31 -0700762 } else {
Michael Jurkaaa2859a2012-10-24 12:46:49 -0700763 // We add the widgets from left to right, starting after the first page after
764 // the add page. We count down, since the order will be persisted from right
765 // to left, starting after camera.
Jim Miller51117262012-11-04 17:58:09 -0800766 addWidget(widgets[i], insertionIndex, true);
Michael Jurkaaa2859a2012-10-24 12:46:49 -0700767 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700768 }
769 }
Jim Miller51117262012-11-04 17:58:09 -0800770 }
771
772 private int allocateIdForDefaultAppWidget() {
773 int appWidgetId;
774 Resources res = getContext().getResources();
775 ComponentName defaultAppWidget = new ComponentName(
776 res.getString(R.string.widget_default_package_name),
777 res.getString(R.string.widget_default_class_name));
778
779 // Note: we don't support configuring the widget
780 appWidgetId = mAppWidgetHost.allocateAppWidgetId();
781
782 try {
783 mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
Jim Miller51117262012-11-04 17:58:09 -0800784 } catch (IllegalArgumentException e) {
785 Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
786 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
787 appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
788 }
789 return appWidgetId;
Michael Jurka67a871d2012-11-01 18:26:01 -0700790 }
Jim Millerf45bb402013-08-20 18:58:32 -0700791
Michael Jurka67a871d2012-11-01 18:26:01 -0700792 public void checkAppWidgetConsistency() {
793 final int childCount = mAppWidgetContainer.getChildCount();
794 boolean widgetPageExists = false;
795 for (int i = 0; i < childCount; i++) {
Jim Miller51117262012-11-04 17:58:09 -0800796 if (mAppWidgetContainer.isWidgetPage(i)) {
Michael Jurka67a871d2012-11-01 18:26:01 -0700797 widgetPageExists = true;
798 break;
799 }
800 }
801 if (!widgetPageExists) {
Jim Miller51117262012-11-04 17:58:09 -0800802 final int insertPageIndex = getInsertPageIndex();
Michael Jurka67a871d2012-11-01 18:26:01 -0700803
Jim Millerf45bb402013-08-20 18:58:32 -0700804 final boolean userAddedWidgetsEnabled = !widgetsDisabled();
805
Jim Miller51117262012-11-04 17:58:09 -0800806 boolean addedDefaultAppWidget = false;
Michael Jurka67a871d2012-11-01 18:26:01 -0700807
Jim Miller51117262012-11-04 17:58:09 -0800808 if (!mSafeModeEnabled) {
809 if (userAddedWidgetsEnabled) {
810 int appWidgetId = allocateIdForDefaultAppWidget();
811 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
812 addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true);
813 }
814 } else {
815 // note: even if widgetsDisabledByDpm() returns true, we still bind/create
816 // the default appwidget if possible
817 int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId();
818 if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
819 appWidgetId = allocateIdForDefaultAppWidget();
820 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
821 mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId);
822 }
823 }
824 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
825 addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false);
826 if (!addedDefaultAppWidget) {
827 mAppWidgetHost.deleteAppWidgetId(appWidgetId);
828 mLockPatternUtils.writeFallbackAppWidgetId(
829 AppWidgetManager.INVALID_APPWIDGET_ID);
830 }
831 }
832 }
Michael Jurka67a871d2012-11-01 18:26:01 -0700833 }
Jim Miller51117262012-11-04 17:58:09 -0800834
Michael Jurka67a871d2012-11-01 18:26:01 -0700835 // Use the built-in status/clock view if we can't inflate the default widget
Jim Miller51117262012-11-04 17:58:09 -0800836 if (!addedDefaultAppWidget) {
837 addDefaultStatusWidget(insertPageIndex);
Michael Jurka67a871d2012-11-01 18:26:01 -0700838 }
Jim Miller51117262012-11-04 17:58:09 -0800839
840 // trigger DB updates only if user-added widgets are enabled
841 if (!mSafeModeEnabled && userAddedWidgetsEnabled) {
842 mAppWidgetContainer.onAddView(
843 mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
844 }
Michael Jurka67a871d2012-11-01 18:26:01 -0700845 }
Adam Cohen0207c092012-09-30 16:11:00 -0700846 }
847
Jim Miller81190be2013-11-05 18:17:59 -0800848 private final Runnable mSwitchPageRunnable = new Runnable() {
Jim Miller223ce5c2012-10-05 19:13:23 -0700849 @Override
850 public void run() {
851 showAppropriateWidgetPage();
Adam Cohen0207c092012-09-30 16:11:00 -0700852 }
Jim Miller223ce5c2012-10-05 19:13:23 -0700853 };
854
855 static class SavedState extends BaseSavedState {
856 int transportState;
Michael Jurka14138892012-11-07 13:45:53 -0800857 int appWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
John Spurlock256ae672013-09-26 12:14:33 -0400858 Rect insets = new Rect();
Jim Miller223ce5c2012-10-05 19:13:23 -0700859
860 SavedState(Parcelable superState) {
861 super(superState);
862 }
863
864 private SavedState(Parcel in) {
865 super(in);
866 this.transportState = in.readInt();
Michael Jurka14138892012-11-07 13:45:53 -0800867 this.appWidgetToShow = in.readInt();
John Spurlock256ae672013-09-26 12:14:33 -0400868 this.insets = in.readParcelable(null);
Jim Miller223ce5c2012-10-05 19:13:23 -0700869 }
870
871 @Override
872 public void writeToParcel(Parcel out, int flags) {
873 super.writeToParcel(out, flags);
874 out.writeInt(this.transportState);
Michael Jurka14138892012-11-07 13:45:53 -0800875 out.writeInt(this.appWidgetToShow);
John Spurlock256ae672013-09-26 12:14:33 -0400876 out.writeParcelable(insets, 0);
Jim Miller223ce5c2012-10-05 19:13:23 -0700877 }
878
879 public static final Parcelable.Creator<SavedState> CREATOR
880 = new Parcelable.Creator<SavedState>() {
881 public SavedState createFromParcel(Parcel in) {
882 return new SavedState(in);
883 }
884
885 public SavedState[] newArray(int size) {
886 return new SavedState[size];
887 }
888 };
889 }
890
891 @Override
892 public Parcelable onSaveInstanceState() {
Jim Miller4894a012013-04-03 15:23:55 -0700893 if (DEBUG) Log.d(TAG, "onSaveInstanceState, tstate=" + mTransportState);
Jim Miller223ce5c2012-10-05 19:13:23 -0700894 Parcelable superState = super.onSaveInstanceState();
895 SavedState ss = new SavedState(superState);
Jim Miller4894a012013-04-03 15:23:55 -0700896 // If the transport is showing, force it to show it on restore.
897 final boolean showing = mTransportControl != null
898 && mAppWidgetContainer.getWidgetPageIndex(mTransportControl) >= 0;
899 ss.transportState = showing ? TRANSPORT_VISIBLE : mTransportState;
Michael Jurka14138892012-11-07 13:45:53 -0800900 ss.appWidgetToShow = mAppWidgetToShow;
John Spurlock256ae672013-09-26 12:14:33 -0400901 ss.insets.set(mInsets);
Jim Miller223ce5c2012-10-05 19:13:23 -0700902 return ss;
903 }
904
905 @Override
906 public void onRestoreInstanceState(Parcelable state) {
907 if (!(state instanceof SavedState)) {
908 super.onRestoreInstanceState(state);
909 return;
910 }
911 SavedState ss = (SavedState) state;
912 super.onRestoreInstanceState(ss.getSuperState());
Jim Miller8f09fd22013-03-14 19:04:28 -0700913 mTransportState = (ss.transportState);
Michael Jurka14138892012-11-07 13:45:53 -0800914 mAppWidgetToShow = ss.appWidgetToShow;
John Spurlock256ae672013-09-26 12:14:33 -0400915 setInsets(ss.insets);
Jim Miller4894a012013-04-03 15:23:55 -0700916 if (DEBUG) Log.d(TAG, "onRestoreInstanceState, transport=" + mTransportState);
Jim Miller81190be2013-11-05 18:17:59 -0800917 mSwitchPageRunnable.run();
Jim Miller223ce5c2012-10-05 19:13:23 -0700918 }
919
John Spurlock5f050e52012-10-27 10:44:19 -0400920 @Override
John Spurlock256ae672013-09-26 12:14:33 -0400921 protected boolean fitSystemWindows(Rect insets) {
922 setInsets(insets);
923 return true;
924 }
925
926 private void setInsets(Rect insets) {
927 mInsets.set(insets);
928 if (mSlidingChallengeLayout != null) mSlidingChallengeLayout.setInsets(mInsets);
929 if (mMultiPaneChallengeLayout != null) mMultiPaneChallengeLayout.setInsets(mInsets);
Daniel Sandler26b7bf62013-10-10 12:44:12 -0400930
931 final CameraWidgetFrame cameraWidget = findCameraPage();
932 if (cameraWidget != null) cameraWidget.setInsets(mInsets);
John Spurlock256ae672013-09-26 12:14:33 -0400933 }
934
935 @Override
John Spurlock5f050e52012-10-27 10:44:19 -0400936 public void onWindowFocusChanged(boolean hasWindowFocus) {
937 super.onWindowFocusChanged(hasWindowFocus);
938 if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
Michael Jurka76017ca2012-11-06 16:21:09 -0800939 if (hasWindowFocus && mShowSecurityWhenReturn) {
Jim Milleraaf9b112012-10-31 19:44:56 -0700940 SlidingChallengeLayout slider =
941 (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
942 if (slider != null) {
943 slider.setHandleAlpha(1);
944 slider.showChallenge(true);
945 }
946 mShowSecurityWhenReturn = false;
John Spurlock5f050e52012-10-27 10:44:19 -0400947 }
948 }
949
Jim Miller4d20ed32013-10-19 01:00:16 +0000950 private void showAppropriateWidgetPage() {
Jim Miller81190be2013-11-05 18:17:59 -0800951 final int state = mTransportState;
952 final boolean transportAdded = ensureTransportPresentOrRemoved(state);
953 final int pageToShow = getAppropriateWidgetPage(state);
954 if (!transportAdded) {
955 mAppWidgetContainer.setCurrentPage(pageToShow);
956 } else if (state == TRANSPORT_VISIBLE) {
957 // If the transport was just added, we need to wait for layout to happen before
958 // we can set the current page.
959 post(new Runnable() {
960 @Override
961 public void run() {
962 mAppWidgetContainer.setCurrentPage(pageToShow);
963 }
964 });
965 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700966 }
967
Jim Miller4894a012013-04-03 15:23:55 -0700968 /**
969 * Examines the current state and adds the transport to the widget pager when the state changes.
970 *
971 * Showing the initial transport and keeping it around is a bit tricky because the signals
972 * coming from music players aren't always clear. Here's how the states are handled:
973 *
974 * {@link TRANSPORT_GONE} means we have no reason to show the transport - remove it if present.
975 *
976 * {@link TRANSPORT_INVISIBLE} means we have potential to show the transport because a music
977 * player is registered but not currently playing music (or we don't know the state yet). The
978 * code adds it conditionally on play state.
979 *
980 * {@link #TRANSPORT_VISIBLE} means a music player is active and transport should be showing.
981 *
982 * Once the transport is showing, we always show it until keyguard is dismissed. This state is
983 * maintained by onSave/RestoreInstanceState(). This state is cleared in
984 * {@link KeyguardViewManager#hide} when keyguard is dismissed, which causes the transport to be
985 * gone when keyguard is restarted until we get an update with the current state.
986 *
987 * @param state
988 */
Jim Miller81190be2013-11-05 18:17:59 -0800989 private boolean ensureTransportPresentOrRemoved(int state) {
Jim Miller4894a012013-04-03 15:23:55 -0700990 final boolean showing = getWidgetPosition(R.id.keyguard_transport_control) != -1;
991 final boolean visible = state == TRANSPORT_VISIBLE;
992 final boolean shouldBeVisible = state == TRANSPORT_INVISIBLE && isMusicPlaying(state);
993 if (!showing && (visible || shouldBeVisible)) {
Jim Miller4894a012013-04-03 15:23:55 -0700994 // insert to left of camera if it exists, otherwise after right-most widget
995 int lastWidget = mAppWidgetContainer.getChildCount() - 1;
996 int position = 0; // handle no widget case
997 if (lastWidget >= 0) {
998 position = mAppWidgetContainer.isCameraPage(lastWidget) ?
999 lastWidget : lastWidget + 1;
Jim Miller8f09fd22013-03-14 19:04:28 -07001000 }
Jim Miller81190be2013-11-05 18:17:59 -08001001 if (DEBUGXPORT) Log.v(TAG, "add transport at " + position);
Jim Miller4894a012013-04-03 15:23:55 -07001002 mAppWidgetContainer.addWidget(getOrCreateTransportControl(), position);
Jim Miller81190be2013-11-05 18:17:59 -08001003 return true;
Jim Miller4894a012013-04-03 15:23:55 -07001004 } else if (showing && state == TRANSPORT_GONE) {
Jim Miller8f09fd22013-03-14 19:04:28 -07001005 if (DEBUGXPORT) Log.v(TAG, "remove transport");
Jim Miller4894a012013-04-03 15:23:55 -07001006 mAppWidgetContainer.removeWidget(getOrCreateTransportControl());
Jim Miller8f09fd22013-03-14 19:04:28 -07001007 mTransportControl = null;
Adam Powell43a372f2013-09-27 17:43:53 -07001008 KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(null);
Jim Miller8f09fd22013-03-14 19:04:28 -07001009 }
Jim Miller81190be2013-11-05 18:17:59 -08001010 return false;
Jim Miller8f09fd22013-03-14 19:04:28 -07001011 }
1012
John Spurlockdbe24b72012-11-01 13:01:05 -04001013 private CameraWidgetFrame findCameraPage() {
1014 for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
Winson Chung6cf53bb2012-11-05 17:55:42 -08001015 if (mAppWidgetContainer.isCameraPage(i)) {
John Spurlockdbe24b72012-11-01 13:01:05 -04001016 return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
1017 }
1018 }
1019 return null;
1020 }
1021
Winson Chung6cf53bb2012-11-05 17:55:42 -08001022 boolean isMusicPage(int pageIndex) {
1023 return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
1024 }
1025
Jim Miller8f09fd22013-03-14 19:04:28 -07001026 private int getAppropriateWidgetPage(int musicTransportState) {
John Spurlock358148e2012-10-26 15:29:59 -04001027 // assumes at least one widget (besides camera + add)
Michael Jurka76017ca2012-11-06 16:21:09 -08001028 if (mAppWidgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
1029 final int childCount = mAppWidgetContainer.getChildCount();
1030 for (int i = 0; i < childCount; i++) {
1031 if (mAppWidgetContainer.getWidgetPageAt(i).getContentAppWidgetId()
1032 == mAppWidgetToShow) {
Michael Jurka76017ca2012-11-06 16:21:09 -08001033 return i;
1034 }
1035 }
1036 mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1037 }
John Spurlock358148e2012-10-26 15:29:59 -04001038 // if music playing, show transport
Jim Miller8f09fd22013-03-14 19:04:28 -07001039 if (musicTransportState == TRANSPORT_VISIBLE) {
John Spurlock358148e2012-10-26 15:29:59 -04001040 if (DEBUG) Log.d(TAG, "Music playing, show transport");
Jim Miller4894a012013-04-03 15:23:55 -07001041 return mAppWidgetContainer.getWidgetPageIndex(getOrCreateTransportControl());
John Spurlock358148e2012-10-26 15:29:59 -04001042 }
1043
John Spurlock5f050e52012-10-27 10:44:19 -04001044 // else show the right-most widget (except for camera)
John Spurlock358148e2012-10-26 15:29:59 -04001045 int rightMost = mAppWidgetContainer.getChildCount() - 1;
Winson Chung6cf53bb2012-11-05 17:55:42 -08001046 if (mAppWidgetContainer.isCameraPage(rightMost)) {
John Spurlock358148e2012-10-26 15:29:59 -04001047 rightMost--;
1048 }
John Spurlock5f050e52012-10-27 10:44:19 -04001049 if (DEBUG) Log.d(TAG, "Show right-most page " + rightMost);
John Spurlock358148e2012-10-26 15:29:59 -04001050 return rightMost;
1051 }
1052
Jim Miller19a52672012-10-23 19:52:04 -07001053 private void enableUserSelectorIfNecessary() {
Jim Miller26e6c2e2012-10-30 14:12:22 -07001054 if (!UserManager.supportsMultipleUsers()) {
1055 return; // device doesn't support multi-user mode
1056 }
Jim Millerf6ab5f92012-11-07 16:15:13 -08001057 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Chris Wrend2dec002012-11-07 16:38:33 -05001058 if (um == null) {
1059 Throwable t = new Throwable();
1060 t.fillInStackTrace();
1061 Log.e(TAG, "user service is null.", t);
1062 return;
1063 }
Jim Miller26e6c2e2012-10-30 14:12:22 -07001064
John Spurlock5f050e52012-10-27 10:44:19 -04001065 // if there are multiple users, we need to enable to multi-user switcher
Jim Millerf6ab5f92012-11-07 16:15:13 -08001066 final List<UserInfo> users = um.getUsers(true);
Chris Wrend2dec002012-11-07 16:38:33 -05001067 if (users == null) {
1068 Throwable t = new Throwable();
1069 t.fillInStackTrace();
1070 Log.e(TAG, "list of users is null.", t);
1071 return;
1072 }
Adam Cohen66b9fb1662012-09-05 16:23:58 -07001073
Jim Millerf6ab5f92012-11-07 16:15:13 -08001074 final View multiUserView = findViewById(R.id.keyguard_user_selector);
1075 if (multiUserView == null) {
1076 Throwable t = new Throwable();
1077 t.fillInStackTrace();
1078 Log.e(TAG, "can't find user_selector in layout.", t);
1079 return;
1080 }
1081
Chris Wrend2dec002012-11-07 16:38:33 -05001082 if (users.size() > 1) {
Chris Wren91f080c2012-11-07 15:20:27 -05001083 if (multiUserView instanceof KeyguardMultiUserSelectorView) {
Chris Wrenf41c61b2012-11-29 15:19:54 -05001084 mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
1085 mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
1086 mKeyguardMultiUserSelectorView.addUsers(users);
Chris Wren91f080c2012-11-07 15:20:27 -05001087 UserSwitcherCallback callback = new UserSwitcherCallback() {
1088 @Override
1089 public void hideSecurityView(int duration) {
Jim Miller3eb49712014-01-28 18:22:42 -08001090 getSecurityContainer().animate().alpha(0).setDuration(duration);
Jim Miller0ff7f012012-10-11 20:40:01 -07001091 }
Adam Cohen0a8d3262012-10-03 13:50:55 -07001092
Chris Wren91f080c2012-11-07 15:20:27 -05001093 @Override
1094 public void showSecurityView() {
Jim Miller3eb49712014-01-28 18:22:42 -08001095 getSecurityContainer().setAlpha(1.0f);
Jim Miller19a52672012-10-23 19:52:04 -07001096 }
Chris Wren91f080c2012-11-07 15:20:27 -05001097
1098 @Override
1099 public void showUnlockHint() {
Jim Miller3eb49712014-01-28 18:22:42 -08001100 if (getSecurityContainer() != null) {
1101 getSecurityContainer().showUsabilityHint();
Chris Wren91f080c2012-11-07 15:20:27 -05001102 }
1103 }
1104
1105 @Override
1106 public void userActivity() {
1107 if (mViewMediatorCallback != null) {
1108 mViewMediatorCallback.userActivity();
1109 }
1110 }
1111 };
Chris Wrenf41c61b2012-11-29 15:19:54 -05001112 mKeyguardMultiUserSelectorView.setCallback(callback);
Chris Wrend2dec002012-11-07 16:38:33 -05001113 } else {
1114 Throwable t = new Throwable();
1115 t.fillInStackTrace();
1116 if (multiUserView == null) {
1117 Log.e(TAG, "could not find the user_selector.", t);
1118 } else {
1119 Log.e(TAG, "user_selector is the wrong type.", t);
1120 }
Chris Wren91f080c2012-11-07 15:20:27 -05001121 }
Adam Cohen66b9fb1662012-09-05 16:23:58 -07001122 }
1123 }
1124
Jim Millerdcb3d842012-08-23 19:18:12 -07001125 @Override
1126 public void cleanUp() {
Adam Cohen128f2762013-04-18 13:37:05 -07001127 // Make sure we let go of all widgets and their package contexts promptly. If we don't do
1128 // this, and the associated application is uninstalled, it can cause a soft reboot.
1129 int count = mAppWidgetContainer.getChildCount();
1130 for (int i = 0; i < count; i++) {
1131 KeyguardWidgetFrame frame = mAppWidgetContainer.getWidgetPageAt(i);
1132 frame.removeAllViews();
1133 }
Jim Millerdcb3d842012-08-23 19:18:12 -07001134 }
1135
Michael Jurka76017ca2012-11-06 16:21:09 -08001136 public void goToWidget(int appWidgetId) {
1137 mAppWidgetToShow = appWidgetId;
1138 mSwitchPageRunnable.run();
1139 }
1140
Jim Miller3eb49712014-01-28 18:22:42 -08001141 @Override
1142 protected void showBouncer(boolean show) {
1143 super.showBouncer(show);
1144 mViewStateManager.showBouncer(show);
Jim Miller4eeb4f62012-11-08 00:04:29 -08001145 }
Jim Millercaf24fc2013-09-10 18:37:01 -07001146
Jim Miller5e612cf2014-02-03 17:57:23 -08001147 @Override
1148 public void onExternalMotionEvent(MotionEvent event) {
Jim Millercaf24fc2013-09-10 18:37:01 -07001149 mAppWidgetContainer.handleExternalCameraEvent(event);
1150 }
1151
Jim Miller5e612cf2014-02-03 17:57:23 -08001152 @Override
1153 protected void onCreateOptions(Bundle options) {
1154 if (options != null) {
1155 int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
1156 AppWidgetManager.INVALID_APPWIDGET_ID);
1157 if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
1158 goToWidget(widgetToShow);
1159 }
1160 }
1161 }
1162
Jim Millerdcb3d842012-08-23 19:18:12 -07001163}