OSDN Git Service

Remove dead code #7: Remove unused SysUI resources
[android-x86/frameworks-base.git] / packages / Keyguard / src / com / android / keyguard / KeyguardHostView.java
1 /*
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
17 package com.android.keyguard;
18
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.graphics.Canvas;
24 import android.media.AudioManager;
25 import android.os.Bundle;
26 import android.os.SystemClock;
27 import android.telephony.TelephonyManager;
28 import android.util.AttributeSet;
29 import android.util.Log;
30 import android.view.KeyEvent;
31 import android.view.MotionEvent;
32 import android.widget.FrameLayout;
33
34 import com.android.internal.widget.LockPatternUtils;
35 import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
36 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
37
38 import java.io.File;
39
40 /**
41  * Base class for keyguard view.  {@link #reset} is where you should
42  * reset the state of your view.  Use the {@link KeyguardViewCallback} via
43  * {@link #getCallback()} to send information back (such as poking the wake lock,
44  * or finishing the keyguard).
45  *
46  * Handles intercepting of media keys that still work when the keyguard is
47  * showing.
48  */
49 public class KeyguardHostView extends FrameLayout implements SecurityCallback {
50
51     public interface OnDismissAction {
52         /**
53          * @return true if the dismiss should be deferred
54          */
55         boolean onDismiss();
56     }
57
58     private AudioManager mAudioManager;
59     private TelephonyManager mTelephonyManager = null;
60     protected ViewMediatorCallback mViewMediatorCallback;
61     protected LockPatternUtils mLockPatternUtils;
62     private OnDismissAction mDismissAction;
63
64     private final KeyguardUpdateMonitorCallback mUpdateCallback =
65             new KeyguardUpdateMonitorCallback() {
66
67         @Override
68         public void onUserSwitchComplete(int userId) {
69             getSecurityContainer().showPrimarySecurityScreen(false /* turning off */);
70         }
71
72         @Override
73         public void onTrustInitiatedByUser(int userId) {
74             if (userId != mLockPatternUtils.getCurrentUser()) return;
75             if (!isAttachedToWindow()) return;
76
77             if (isVisibleToUser()) {
78                 dismiss(false /* authenticated */);
79             } else {
80                 mViewMediatorCallback.playTrustedSound();
81             }
82         }
83     };
84
85     // Whether the volume keys should be handled by keyguard. If true, then
86     // they will be handled here for specific media types such as music, otherwise
87     // the audio service will bring up the volume dialog.
88     private static final boolean KEYGUARD_MANAGES_VOLUME = false;
89     public static final boolean DEBUG = KeyguardConstants.DEBUG;
90     private static final String TAG = "KeyguardViewBase";
91
92     private KeyguardSecurityContainer mSecurityContainer;
93
94     public KeyguardHostView(Context context) {
95         this(context, null);
96     }
97
98     public KeyguardHostView(Context context, AttributeSet attrs) {
99         super(context, attrs);
100         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateCallback);
101     }
102
103     @Override
104     protected void dispatchDraw(Canvas canvas) {
105         super.dispatchDraw(canvas);
106         if (mViewMediatorCallback != null) {
107             mViewMediatorCallback.keyguardDoneDrawing();
108         }
109     }
110
111     /**
112      * Sets an action to run when keyguard finishes.
113      *
114      * @param action
115      */
116     public void setOnDismissAction(OnDismissAction action) {
117         mDismissAction = action;
118     }
119
120     @Override
121     protected void onFinishInflate() {
122         mSecurityContainer =
123                 (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
124         mLockPatternUtils = new LockPatternUtils(mContext);
125         mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
126         mSecurityContainer.setSecurityCallback(this);
127         mSecurityContainer.showPrimarySecurityScreen(false);
128         // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
129     }
130
131     /**
132      * Called when the view needs to be shown.
133      */
134     public void showPrimarySecurityScreen() {
135         if (DEBUG) Log.d(TAG, "show()");
136         mSecurityContainer.showPrimarySecurityScreen(false);
137     }
138
139     /**
140      *  Dismisses the keyguard by going to the next screen or making it gone.
141      *
142      *  @return True if the keyguard is done.
143      */
144     public boolean dismiss() {
145         return dismiss(false);
146     }
147
148     public boolean handleBackKey() {
149         if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
150             mSecurityContainer.dismiss(false);
151             return true;
152         }
153         return false;
154     }
155
156     protected KeyguardSecurityContainer getSecurityContainer() {
157         return mSecurityContainer;
158     }
159
160     @Override
161     public boolean dismiss(boolean authenticated) {
162         return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
163     }
164
165     /**
166      * Authentication has happened and it's time to dismiss keyguard. This function
167      * should clean up and inform KeyguardViewMediator.
168      */
169     @Override
170     public void finish() {
171         // If the alternate unlock was suppressed, it can now be safely
172         // enabled because the user has left keyguard.
173         KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
174
175         // If there's a pending runnable because the user interacted with a widget
176         // and we're leaving keyguard, then run it.
177         boolean deferKeyguardDone = false;
178         if (mDismissAction != null) {
179             deferKeyguardDone = mDismissAction.onDismiss();
180             mDismissAction = null;
181         }
182         if (mViewMediatorCallback != null) {
183             if (deferKeyguardDone) {
184                 mViewMediatorCallback.keyguardDonePending();
185             } else {
186                 mViewMediatorCallback.keyguardDone(true);
187             }
188         }
189     }
190
191     @Override
192     public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
193         if (mViewMediatorCallback != null) {
194             mViewMediatorCallback.setNeedsInput(needsInput);
195         }
196     }
197
198     public void userActivity() {
199         if (mViewMediatorCallback != null) {
200             mViewMediatorCallback.userActivity();
201         }
202     }
203
204     /**
205      * Called when the Keyguard is not actively shown anymore on the screen.
206      */
207     public void onPause() {
208         if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
209                 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
210         // Once the screen turns off, we no longer consider this to be first boot and we want the
211         // biometric unlock to start next time keyguard is shown.
212         KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
213         mSecurityContainer.showPrimarySecurityScreen(true);
214         mSecurityContainer.onPause();
215         clearFocus();
216     }
217
218     /**
219      * Called when the Keyguard is actively shown on the screen.
220      */
221     public void onResume() {
222         if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
223         mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
224         requestFocus();
225     }
226
227     /**
228      * Starts the animation when the Keyguard gets shown.
229      */
230     public void startAppearAnimation() {
231         mSecurityContainer.startAppearAnimation();
232     }
233
234     public void startDisappearAnimation(Runnable finishRunnable) {
235         if (!mSecurityContainer.startDisappearAnimation(finishRunnable) && finishRunnable != null) {
236             finishRunnable.run();
237         }
238     }
239
240     /**
241      * Verify that the user can get past the keyguard securely.  This is called,
242      * for example, when the phone disables the keyguard but then wants to launch
243      * something else that requires secure access.
244      *
245      * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
246      */
247     public void verifyUnlock() {
248         SecurityMode securityMode = mSecurityContainer.getSecurityMode();
249         if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
250             if (mViewMediatorCallback != null) {
251                 mViewMediatorCallback.keyguardDone(true);
252             }
253         } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
254                 && securityMode != KeyguardSecurityModel.SecurityMode.PIN
255                 && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
256             // can only verify unlock when in pattern/password mode
257             if (mViewMediatorCallback != null) {
258                 mViewMediatorCallback.keyguardDone(false);
259             }
260         } else {
261             // otherwise, go to the unlock screen, see if they can verify it
262             mSecurityContainer.verifyUnlock();
263         }
264     }
265
266     /**
267      * Called before this view is being removed.
268      */
269     public void cleanUp() {
270         getSecurityContainer().onPause();
271     }
272
273     @Override
274     public boolean dispatchKeyEvent(KeyEvent event) {
275         if (interceptMediaKey(event)) {
276             return true;
277         }
278         return super.dispatchKeyEvent(event);
279     }
280
281     /**
282      * Allows the media keys to work when the keyguard is showing.
283      * The media keys should be of no interest to the actual keyguard view(s),
284      * so intercepting them here should not be of any harm.
285      * @param event The key event
286      * @return whether the event was consumed as a media key.
287      */
288     public boolean interceptMediaKey(KeyEvent event) {
289         final int keyCode = event.getKeyCode();
290         if (event.getAction() == KeyEvent.ACTION_DOWN) {
291             switch (keyCode) {
292                 case KeyEvent.KEYCODE_MEDIA_PLAY:
293                 case KeyEvent.KEYCODE_MEDIA_PAUSE:
294                 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
295                     /* Suppress PLAY/PAUSE toggle when phone is ringing or
296                      * in-call to avoid music playback */
297                     if (mTelephonyManager == null) {
298                         mTelephonyManager = (TelephonyManager) getContext().getSystemService(
299                                 Context.TELEPHONY_SERVICE);
300                     }
301                     if (mTelephonyManager != null &&
302                             mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
303                         return true;  // suppress key event
304                     }
305                 case KeyEvent.KEYCODE_MUTE:
306                 case KeyEvent.KEYCODE_HEADSETHOOK:
307                 case KeyEvent.KEYCODE_MEDIA_STOP:
308                 case KeyEvent.KEYCODE_MEDIA_NEXT:
309                 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
310                 case KeyEvent.KEYCODE_MEDIA_REWIND:
311                 case KeyEvent.KEYCODE_MEDIA_RECORD:
312                 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
313                 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
314                     handleMediaKeyEvent(event);
315                     return true;
316                 }
317
318                 case KeyEvent.KEYCODE_VOLUME_UP:
319                 case KeyEvent.KEYCODE_VOLUME_DOWN:
320                 case KeyEvent.KEYCODE_VOLUME_MUTE: {
321                     if (KEYGUARD_MANAGES_VOLUME) {
322                         synchronized (this) {
323                             if (mAudioManager == null) {
324                                 mAudioManager = (AudioManager) getContext().getSystemService(
325                                         Context.AUDIO_SERVICE);
326                             }
327                         }
328                         // Volume buttons should only function for music (local or remote).
329                         // TODO: Actually handle MUTE.
330                         mAudioManager.adjustSuggestedStreamVolume(
331                                 keyCode == KeyEvent.KEYCODE_VOLUME_UP
332                                         ? AudioManager.ADJUST_RAISE
333                                         : AudioManager.ADJUST_LOWER /* direction */,
334                                 AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
335                         // Don't execute default volume behavior
336                         return true;
337                     } else {
338                         return false;
339                     }
340                 }
341             }
342         } else if (event.getAction() == KeyEvent.ACTION_UP) {
343             switch (keyCode) {
344                 case KeyEvent.KEYCODE_MUTE:
345                 case KeyEvent.KEYCODE_HEADSETHOOK:
346                 case KeyEvent.KEYCODE_MEDIA_PLAY:
347                 case KeyEvent.KEYCODE_MEDIA_PAUSE:
348                 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
349                 case KeyEvent.KEYCODE_MEDIA_STOP:
350                 case KeyEvent.KEYCODE_MEDIA_NEXT:
351                 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
352                 case KeyEvent.KEYCODE_MEDIA_REWIND:
353                 case KeyEvent.KEYCODE_MEDIA_RECORD:
354                 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
355                 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
356                     handleMediaKeyEvent(event);
357                     return true;
358                 }
359             }
360         }
361         return false;
362     }
363
364     private void handleMediaKeyEvent(KeyEvent keyEvent) {
365         synchronized (this) {
366             if (mAudioManager == null) {
367                 mAudioManager = (AudioManager) getContext().getSystemService(
368                         Context.AUDIO_SERVICE);
369             }
370         }
371         mAudioManager.dispatchMediaKeyEvent(keyEvent);
372     }
373
374     @Override
375     public void dispatchSystemUiVisibilityChanged(int visibility) {
376         super.dispatchSystemUiVisibilityChanged(visibility);
377
378         if (!(mContext instanceof Activity)) {
379             setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
380         }
381     }
382
383     /**
384      * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
385      * some cases where we wish to disable it, notably when the menu button placement or technology
386      * is prone to false positives.
387      *
388      * @return true if the menu key should be enabled
389      */
390     private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
391     private boolean shouldEnableMenuKey() {
392         final Resources res = getResources();
393         final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
394         final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
395         final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
396         return !configDisabled || isTestHarness || fileOverride;
397     }
398
399     public boolean handleMenuKey() {
400         // The following enables the MENU key to work for testing automation
401         if (shouldEnableMenuKey()) {
402             dismiss();
403             return true;
404         }
405         return false;
406     }
407
408     public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
409         mViewMediatorCallback = viewMediatorCallback;
410         // Update ViewMediator with the current input method requirements
411         mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
412     }
413
414     public void setLockPatternUtils(LockPatternUtils utils) {
415         mLockPatternUtils = utils;
416         mSecurityContainer.setLockPatternUtils(utils);
417     }
418
419     public SecurityMode getSecurityMode() {
420         return mSecurityContainer.getSecurityMode();
421     }
422
423     public SecurityMode getCurrentSecurityMode() {
424         return mSecurityContainer.getCurrentSecurityMode();
425     }
426
427
428 }