blob: 78f4506e61bac174108c745eba3f7e4817973a5e [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080018
Jim Millerd6523da2012-10-21 16:47:02 -070019import android.app.Activity;
Jim Miller3eb49712014-01-28 18:22:42 -080020import android.app.ActivityManager;
21import android.app.ActivityOptions;
22import android.app.SearchManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080023import android.content.Context;
Jim Miller3eb49712014-01-28 18:22:42 -080024import android.content.Intent;
25import android.content.res.Resources;
26import android.graphics.Canvas;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080027import android.media.AudioManager;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070028import android.media.IAudioService;
Jim Miller5e612cf2014-02-03 17:57:23 -080029import android.os.Bundle;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070030import android.os.RemoteException;
31import android.os.ServiceManager;
Jim Miller3eb49712014-01-28 18:22:42 -080032import android.os.SystemClock;
33import android.os.UserHandle;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080034import android.telephony.TelephonyManager;
Karl Rosaenad297342009-03-24 18:55:19 -070035import android.util.AttributeSet;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070036import android.util.Log;
37import android.util.Slog;
Jim Miller838906b2012-10-19 18:41:25 -070038import android.view.KeyEvent;
Jim Miller5e612cf2014-02-03 17:57:23 -080039import android.view.MotionEvent;
Jim Miller3eb49712014-01-28 18:22:42 -080040import android.view.View;
Jim Miller838906b2012-10-19 18:41:25 -070041import android.widget.FrameLayout;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080042
Jim Miller3eb49712014-01-28 18:22:42 -080043import com.android.internal.widget.LockPatternUtils;
44import com.android.keyguard.KeyguardHostView.OnDismissAction;
45import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
46import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
47
48import java.io.File;
49
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080050/**
Jim Millerdcb3d842012-08-23 19:18:12 -070051 * Base class for keyguard view. {@link #reset} is where you should
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080052 * reset the state of your view. Use the {@link KeyguardViewCallback} via
53 * {@link #getCallback()} to send information back (such as poking the wake lock,
54 * or finishing the keyguard).
55 *
56 * Handles intercepting of media keys that still work when the keyguard is
57 * showing.
58 */
Jim Millerba7d94b2014-02-05 17:30:50 -080059public abstract class KeyguardViewBase extends FrameLayout implements SecurityCallback {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080060
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080061 private AudioManager mAudioManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080062 private TelephonyManager mTelephonyManager = null;
Jim Millerdcb3d842012-08-23 19:18:12 -070063 protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
Jim Miller3eb49712014-01-28 18:22:42 -080064 protected LockPatternUtils mLockPatternUtils;
65 private OnDismissAction mDismissAction;
Jim Millerdcb3d842012-08-23 19:18:12 -070066
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -080067 // Whether the volume keys should be handled by keyguard. If true, then
68 // they will be handled here for specific media types such as music, otherwise
69 // the audio service will bring up the volume dialog.
Amith Yamasani6243edd2011-12-05 19:58:48 -080070 private static final boolean KEYGUARD_MANAGES_VOLUME = true;
Jim Miller3eb49712014-01-28 18:22:42 -080071 private static final boolean DEBUG = false;
72 private static final String TAG = "KeyguardViewBase";
73
74 private KeyguardSecurityContainer mSecurityContainer;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080075
Jim Millerdcb3d842012-08-23 19:18:12 -070076 public KeyguardViewBase(Context context) {
77 this(context, null);
78 }
79
80 public KeyguardViewBase(Context context, AttributeSet attrs) {
81 super(context, attrs);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080082 }
83
Jim Miller3eb49712014-01-28 18:22:42 -080084 @Override
85 protected void dispatchDraw(Canvas canvas) {
86 super.dispatchDraw(canvas);
87 if (mViewMediatorCallback != null) {
88 mViewMediatorCallback.keyguardDoneDrawing();
89 }
90 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080091
92 /**
Jim Miller3eb49712014-01-28 18:22:42 -080093 * Sets an action to run when keyguard finishes.
94 *
95 * @param action
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096 */
Jim Miller3eb49712014-01-28 18:22:42 -080097 public void setOnDismissAction(OnDismissAction action) {
98 mDismissAction = action;
99 }
100
101 @Override
102 protected void onFinishInflate() {
103 mSecurityContainer =
104 (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
Jim Miller5e612cf2014-02-03 17:57:23 -0800105 mLockPatternUtils = new LockPatternUtils(mContext);
Jim Miller3eb49712014-01-28 18:22:42 -0800106 mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
Jim Millerba7d94b2014-02-05 17:30:50 -0800107 mSecurityContainer.setSecurityCallback(this);
Jim Miller3eb49712014-01-28 18:22:42 -0800108 mSecurityContainer.showPrimarySecurityScreen(false);
109 // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
110 setBackButtonEnabled(false);
111 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800112
113 /**
Brian Colonna4284e9d2011-09-28 12:08:58 -0400114 * Called when the view needs to be shown.
115 */
Jim Miller3eb49712014-01-28 18:22:42 -0800116 public void show() {
117 if (DEBUG) Log.d(TAG, "show()");
118 mSecurityContainer.showPrimarySecurityScreen(false);
119 }
120
121 /**
122 * Dismisses the keyguard by going to the next screen or making it gone.
123 */
124 public void dismiss() {
125 dismiss(false);
126 }
127
Jim Miller3eb49712014-01-28 18:22:42 -0800128 private void setBackButtonEnabled(boolean enabled) {
129 setSystemUiVisibility(enabled ?
130 getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
131 getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
132 }
133
134 protected void showBouncer(boolean show) {
135 CharSequence what = getContext().getResources().getText(
136 show ? R.string.keyguard_accessibility_show_bouncer
137 : R.string.keyguard_accessibility_hide_bouncer);
138 announceForAccessibility(what);
139 announceCurrentSecurityMethod();
140 }
141
142 public boolean handleBackKey() {
143 if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
144 // go back to primary screen and re-disable back
145 setBackButtonEnabled(false);
146 mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
147 return true;
148 }
149 if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
150 mSecurityContainer.dismiss(false);
151 return true;
152 }
153 return false;
154 }
155
156 protected void announceCurrentSecurityMethod() {
157 mSecurityContainer.announceCurrentSecurityMethod();
158 }
159
Jim Millerba7d94b2014-02-05 17:30:50 -0800160 protected KeyguardSecurityContainer getSecurityContainer() {
161 return mSecurityContainer;
162 }
Jim Miller3eb49712014-01-28 18:22:42 -0800163
Jim Millerba7d94b2014-02-05 17:30:50 -0800164 /**
165 * Extend display timeout
166 * @param timeout duration to delay timeout, in ms.
167 */
168 @Override
169 public void userActivity(long timeout) {
Jim Miller3eb49712014-01-28 18:22:42 -0800170 if (mViewMediatorCallback != null) {
Jim Millerba7d94b2014-02-05 17:30:50 -0800171 mViewMediatorCallback.userActivity(timeout);
Jim Miller3eb49712014-01-28 18:22:42 -0800172 }
173 }
174
Jim Millerba7d94b2014-02-05 17:30:50 -0800175 @Override
176 public boolean dismiss(boolean authenticated) {
177 return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
Jim Miller3eb49712014-01-28 18:22:42 -0800178 }
179
180 /**
181 * Authentication has happened and it's time to dismiss keyguard. This function
182 * should clean up and inform KeyguardViewMediator.
183 */
Jim Millerba7d94b2014-02-05 17:30:50 -0800184 @Override
Jim Miller3eb49712014-01-28 18:22:42 -0800185 public void finish() {
186 // If the alternate unlock was suppressed, it can now be safely
187 // enabled because the user has left keyguard.
188 KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
189
190 // If there's a pending runnable because the user interacted with a widget
191 // and we're leaving keyguard, then run it.
192 boolean deferKeyguardDone = false;
193 if (mDismissAction != null) {
194 deferKeyguardDone = mDismissAction.onDismiss();
195 mDismissAction = null;
196 }
197 if (mViewMediatorCallback != null) {
198 if (deferKeyguardDone) {
199 mViewMediatorCallback.keyguardDonePending();
200 } else {
201 mViewMediatorCallback.keyguardDone(true);
202 }
203 }
204 }
205
Jim Millerba7d94b2014-02-05 17:30:50 -0800206 @Override
207 public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
208 // Enable or disable the back button based on security mode
209 if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
210 // we're showing account as a backup, provide a way to get back to primary
211 setBackButtonEnabled(true);
212 }
213
Jim Miller3eb49712014-01-28 18:22:42 -0800214 if (mViewMediatorCallback != null) {
Jim Millerba7d94b2014-02-05 17:30:50 -0800215 mViewMediatorCallback.setNeedsInput(needsInput);
Jim Miller3eb49712014-01-28 18:22:42 -0800216 }
217 }
218
Jim Millerba7d94b2014-02-05 17:30:50 -0800219 public void userActivity() {
Jim Miller3eb49712014-01-28 18:22:42 -0800220 if (mViewMediatorCallback != null) {
221 mViewMediatorCallback.userActivity();
222 }
223 }
224
225 protected void onUserActivityTimeoutChanged() {
226 if (mViewMediatorCallback != null) {
227 mViewMediatorCallback.onUserActivityTimeoutChanged();
228 }
229 }
230
231 /**
232 * Called when the screen turned off.
233 */
234 protected void onScreenTurnedOff() {
235 if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
236 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
237 // Once the screen turns off, we no longer consider this to be first boot and we want the
238 // biometric unlock to start next time keyguard is shown.
239 KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
240 mSecurityContainer.showPrimarySecurityScreen(true);
241 mSecurityContainer.onPause();
242 clearFocus();
243 }
244
245 /**
246 * Called when the screen turned on.
247 */
248 protected void onScreenTurnedOn() {
249 if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
250 mSecurityContainer.showPrimarySecurityScreen(false);
251 mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
252
253 // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
254 // layout is blank but forcing a layout causes it to reappear (e.g. with with
255 // hierarchyviewer).
256 requestLayout();
257 requestFocus();
258 }
Brian Colonna4284e9d2011-09-28 12:08:58 -0400259
260 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800261 * Verify that the user can get past the keyguard securely. This is called,
262 * for example, when the phone disables the keyguard but then wants to launch
263 * something else that requires secure access.
264 *
265 * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
266 */
Jim Miller3eb49712014-01-28 18:22:42 -0800267 public void verifyUnlock() {
Jim Millerba7d94b2014-02-05 17:30:50 -0800268 SecurityMode securityMode = mSecurityContainer.getSecurityMode();
Jim Miller3eb49712014-01-28 18:22:42 -0800269 if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
270 if (mViewMediatorCallback != null) {
271 mViewMediatorCallback.keyguardDone(true);
272 }
273 } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
274 && securityMode != KeyguardSecurityModel.SecurityMode.PIN
275 && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
276 // can only verify unlock when in pattern/password mode
277 if (mViewMediatorCallback != null) {
278 mViewMediatorCallback.keyguardDone(false);
279 }
280 } else {
281 // otherwise, go to the unlock screen, see if they can verify it
282 mSecurityContainer.verifyUnlock();
283 }
284 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800285
286 /**
287 * Called before this view is being removed.
288 */
289 abstract public void cleanUp();
290
Jeff Brownc7505bc2012-10-05 21:58:15 -0700291 /**
292 * Gets the desired user activity timeout in milliseconds, or -1 if the
293 * default should be used.
294 */
295 abstract public long getUserActivityTimeout();
296
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800297 @Override
298 public boolean dispatchKeyEvent(KeyEvent event) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800299 if (interceptMediaKey(event)) {
300 return true;
301 }
302 return super.dispatchKeyEvent(event);
303 }
304
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800305 /**
Marco Nelissen24d10562009-05-12 14:15:17 -0700306 * Allows the media keys to work when the keyguard is showing.
307 * The media keys should be of no interest to the actual keyguard view(s),
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800308 * so intercepting them here should not be of any harm.
309 * @param event The key event
310 * @return whether the event was consumed as a media key.
311 */
312 private boolean interceptMediaKey(KeyEvent event) {
313 final int keyCode = event.getKeyCode();
314 if (event.getAction() == KeyEvent.ACTION_DOWN) {
315 switch (keyCode) {
Marco Nelissena6face42010-10-25 10:21:59 -0700316 case KeyEvent.KEYCODE_MEDIA_PLAY:
317 case KeyEvent.KEYCODE_MEDIA_PAUSE:
Andy Stadler8b89d692009-04-10 16:24:49 -0700318 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
Jeff Brown4d396052010-10-29 21:50:21 -0700319 /* Suppress PLAY/PAUSE toggle when phone is ringing or
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800320 * in-call to avoid music playback */
321 if (mTelephonyManager == null) {
322 mTelephonyManager = (TelephonyManager) getContext().getSystemService(
323 Context.TELEPHONY_SERVICE);
324 }
325 if (mTelephonyManager != null &&
326 mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
327 return true; // suppress key event
328 }
Jeff Brown4d396052010-10-29 21:50:21 -0700329 case KeyEvent.KEYCODE_MUTE:
330 case KeyEvent.KEYCODE_HEADSETHOOK:
331 case KeyEvent.KEYCODE_MEDIA_STOP:
332 case KeyEvent.KEYCODE_MEDIA_NEXT:
333 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
334 case KeyEvent.KEYCODE_MEDIA_REWIND:
335 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900336 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
337 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700338 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800339 return true;
340 }
341
342 case KeyEvent.KEYCODE_VOLUME_UP:
Jeff Brownb0418da2010-11-01 15:24:01 -0700343 case KeyEvent.KEYCODE_VOLUME_DOWN:
344 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800345 if (KEYGUARD_MANAGES_VOLUME) {
346 synchronized (this) {
347 if (mAudioManager == null) {
348 mAudioManager = (AudioManager) getContext().getSystemService(
349 Context.AUDIO_SERVICE);
350 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800351 }
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700352 // Volume buttons should only function for music (local or remote).
353 // TODO: Actually handle MUTE.
354 mAudioManager.adjustLocalOrRemoteStreamVolume(
355 AudioManager.STREAM_MUSIC,
356 keyCode == KeyEvent.KEYCODE_VOLUME_UP
357 ? AudioManager.ADJUST_RAISE
358 : AudioManager.ADJUST_LOWER);
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800359 // Don't execute default volume behavior
360 return true;
361 } else {
362 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800363 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800364 }
365 }
366 } else if (event.getAction() == KeyEvent.ACTION_UP) {
367 switch (keyCode) {
368 case KeyEvent.KEYCODE_MUTE:
Jeff Brown4d396052010-10-29 21:50:21 -0700369 case KeyEvent.KEYCODE_HEADSETHOOK:
370 case KeyEvent.KEYCODE_MEDIA_PLAY:
371 case KeyEvent.KEYCODE_MEDIA_PAUSE:
372 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
373 case KeyEvent.KEYCODE_MEDIA_STOP:
374 case KeyEvent.KEYCODE_MEDIA_NEXT:
375 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
376 case KeyEvent.KEYCODE_MEDIA_REWIND:
377 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900378 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
379 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700380 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800381 return true;
382 }
383 }
384 }
385 return false;
386 }
387
Jim Miller3eb49712014-01-28 18:22:42 -0800388 private void handleMediaKeyEvent(KeyEvent keyEvent) {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700389 IAudioService audioService = IAudioService.Stub.asInterface(
390 ServiceManager.checkService(Context.AUDIO_SERVICE));
391 if (audioService != null) {
392 try {
393 audioService.dispatchMediaKeyEvent(keyEvent);
394 } catch (RemoteException e) {
395 Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
396 }
397 } else {
398 Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
399 }
400 }
401
Joe Onorato4671ce52011-01-27 21:15:42 -0800402 @Override
403 public void dispatchSystemUiVisibilityChanged(int visibility) {
404 super.dispatchSystemUiVisibilityChanged(visibility);
Jim Millerd6523da2012-10-21 16:47:02 -0700405
406 if (!(mContext instanceof Activity)) {
407 setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
408 }
Joe Onorato4671ce52011-01-27 21:15:42 -0800409 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700410
Jim Miller3eb49712014-01-28 18:22:42 -0800411 /**
412 * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
413 * some cases where we wish to disable it, notably when the menu button placement or technology
414 * is prone to false positives.
415 *
416 * @return true if the menu key should be enabled
417 */
418 private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
419 private boolean shouldEnableMenuKey() {
420 final Resources res = getResources();
421 final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
422 final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
423 final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
424 return !configDisabled || isTestHarness || fileOverride;
425 }
426
427 public boolean handleMenuKey() {
428 // The following enables the MENU key to work for testing automation
429 if (shouldEnableMenuKey()) {
430 dismiss();
431 return true;
432 }
433 return false;
434 }
435
Jim Millerdcb3d842012-08-23 19:18:12 -0700436 public void setViewMediatorCallback(
437 KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
438 mViewMediatorCallback = viewMediatorCallback;
Jim Millerba7d94b2014-02-05 17:30:50 -0800439 // Update ViewMediator with the current input method requirements
440 mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
Jim Millerdcb3d842012-08-23 19:18:12 -0700441 }
Jim Miller3eb49712014-01-28 18:22:42 -0800442
443 protected KeyguardActivityLauncher getActivityLauncher() {
444 return mActivityLauncher;
445 }
446
447 private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
448 @Override
449 Context getContext() {
450 return mContext;
451 }
452
453 @Override
454 void setOnDismissAction(OnDismissAction action) {
455 KeyguardViewBase.this.setOnDismissAction(action);
456 }
457
458 @Override
459 LockPatternUtils getLockPatternUtils() {
460 return mLockPatternUtils;
461 }
462
463 @Override
464 void requestDismissKeyguard() {
465 KeyguardViewBase.this.dismiss(false);
466 }
467 };
468
469 public void showAssistant() {
470 final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
471 .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
472
473 if (intent == null) return;
474
475 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
476 R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
477 getHandler(), null);
478
479 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
480 mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
481 }
482
483 public void launchCamera() {
484 mActivityLauncher.launchCamera(getHandler(), null);
485 }
486
Jim Miller5e612cf2014-02-03 17:57:23 -0800487 protected void setLockPatternUtils(LockPatternUtils utils) {
488 mLockPatternUtils = utils;
489 mSecurityContainer.setLockPatternUtils(utils);
490 }
491
492 protected abstract void onUserSwitching(boolean switching);
493
494 protected abstract void onCreateOptions(Bundle options);
495
496 protected abstract void onExternalMotionEvent(MotionEvent event);
497
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800498}