KeyguardViewManager.java revision ee4d45f3052c8d339035c4bb8eca9b7a724e5074
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
17package com.android.internal.policy.impl;
18
19import com.android.internal.R;
20
21import android.app.ActivityManager;
22import android.content.Context;
23import android.content.pm.ActivityInfo;
24import android.content.res.Resources;
25import android.graphics.PixelFormat;
26import android.graphics.Canvas;
27import android.os.IBinder;
28import android.os.SystemProperties;
29import android.util.Log;
30import android.view.View;
31import android.view.ViewGroup;
32import android.view.ViewManager;
33import android.view.WindowManager;
34import android.widget.FrameLayout;
35
36import android.graphics.Color;
37
38/**
39 * Manages creating, showing, hiding and resetting the keyguard.  Calls back
40 * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
41 * the wake lock and report that the keyguard is done, which is in turn,
42 * reported to this class by the current {@link KeyguardViewBase}.
43 */
44public class KeyguardViewManager implements KeyguardWindowController {
45    private final static boolean DEBUG = false;
46    private static String TAG = "KeyguardViewManager";
47
48    private final Context mContext;
49    private final ViewManager mViewManager;
50    private final KeyguardViewCallback mCallback;
51    private final KeyguardViewProperties mKeyguardViewProperties;
52
53    private final KeyguardUpdateMonitor mUpdateMonitor;
54
55    private WindowManager.LayoutParams mWindowLayoutParams;
56    private boolean mNeedsInput = false;
57
58    private FrameLayout mKeyguardHost;
59    private KeyguardViewBase mKeyguardView;
60
61    private boolean mScreenOn = false;
62
63    public interface ShowListener {
64        void onShown(IBinder windowToken);
65    };
66
67    /**
68     * @param context Used to create views.
69     * @param viewManager Keyguard will be attached to this.
70     * @param callback Used to notify of changes.
71     */
72    public KeyguardViewManager(Context context, ViewManager viewManager,
73            KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
74            KeyguardUpdateMonitor updateMonitor) {
75        mContext = context;
76        mViewManager = viewManager;
77        mCallback = callback;
78        mKeyguardViewProperties = keyguardViewProperties;
79
80        mUpdateMonitor = updateMonitor;
81    }
82
83    /**
84     * Helper class to host the keyguard view.
85     */
86    private static class KeyguardViewHost extends FrameLayout {
87        private final KeyguardViewCallback mCallback;
88
89        private KeyguardViewHost(Context context, KeyguardViewCallback callback) {
90            super(context);
91            mCallback = callback;
92        }
93
94        @Override
95        protected void dispatchDraw(Canvas canvas) {
96            super.dispatchDraw(canvas);
97            mCallback.keyguardDoneDrawing();
98        }
99    }
100
101    /**
102     * Show the keyguard.  Will handle creating and attaching to the view manager
103     * lazily.
104     */
105    public synchronized void show() {
106        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
107
108        Resources res = mContext.getResources();
109        boolean enableScreenRotation =
110                SystemProperties.getBoolean("lockscreen.rot_override",false)
111                || res.getBoolean(R.bool.config_enableLockScreenRotation);
112        if (mKeyguardHost == null) {
113            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
114
115            mKeyguardHost = new KeyguardViewHost(mContext, mCallback);
116
117            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
118            int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
119                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
120                    | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
121                    | WindowManager.LayoutParams.FLAG_SLIPPERY
122                    /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
123                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
124            if (!mNeedsInput) {
125                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
126            }
127            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
128                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
129                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
130            }
131            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
132                    stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
133                    flags, PixelFormat.TRANSLUCENT);
134            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
135            lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
136            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
137                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
138                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
139                lp.privateFlags |=
140                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
141            }
142            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
143            lp.setTitle("Keyguard");
144            mWindowLayoutParams = lp;
145
146            mViewManager.addView(mKeyguardHost, lp);
147        }
148
149        if (enableScreenRotation) {
150            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
151            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
152        } else {
153            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
154            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
155        }
156
157        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
158
159        if (mKeyguardView == null) {
160            if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
161            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
162            mKeyguardView.setId(R.id.lock_screen);
163            mKeyguardView.setCallback(mCallback);
164
165            final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
166                    ViewGroup.LayoutParams.MATCH_PARENT,
167                    ViewGroup.LayoutParams.MATCH_PARENT);
168
169            mKeyguardHost.addView(mKeyguardView, lp);
170
171            if (mScreenOn) {
172                mKeyguardView.show();
173            }
174        }
175
176        // Disable aspects of the system/status/navigation bars that are not appropriate or
177        // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
178        // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
179        // status bar service.
180        int visFlags =
181                ( View.STATUS_BAR_DISABLE_BACK
182                | View.STATUS_BAR_DISABLE_HOME
183                );
184        mKeyguardHost.setSystemUiVisibility(visFlags);
185
186        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
187        mKeyguardHost.setVisibility(View.VISIBLE);
188        mKeyguardView.requestFocus();
189    }
190
191    public void setNeedsInput(boolean needsInput) {
192        mNeedsInput = needsInput;
193        if (mWindowLayoutParams != null) {
194            if (needsInput) {
195                mWindowLayoutParams.flags &=
196                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
197            } else {
198                mWindowLayoutParams.flags |=
199                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
200            }
201            mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
202        }
203    }
204
205    /**
206     * Reset the state of the view.
207     */
208    public synchronized void reset() {
209        if (DEBUG) Log.d(TAG, "reset()");
210        if (mKeyguardView != null) {
211            mKeyguardView.reset();
212        }
213    }
214
215    public synchronized void onScreenTurnedOff() {
216        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
217        mScreenOn = false;
218        if (mKeyguardView != null) {
219            mKeyguardView.onScreenTurnedOff();
220        }
221    }
222
223    public synchronized void onScreenTurnedOn(
224            final KeyguardViewManager.ShowListener showListener) {
225        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
226        mScreenOn = true;
227        if (mKeyguardView != null) {
228            mKeyguardView.onScreenTurnedOn();
229
230            // Caller should wait for this window to be shown before turning
231            // on the screen.
232            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
233                // Keyguard may be in the process of being shown, but not yet
234                // updated with the window manager...  give it a chance to do so.
235                mKeyguardHost.post(new Runnable() {
236                    @Override public void run() {
237                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
238                            showListener.onShown(mKeyguardHost.getWindowToken());
239                        } else {
240                            showListener.onShown(null);
241                        }
242                    }
243                });
244            } else {
245                showListener.onShown(null);
246            }
247        } else {
248            showListener.onShown(null);
249        }
250    }
251
252    public synchronized void verifyUnlock() {
253        if (DEBUG) Log.d(TAG, "verifyUnlock()");
254        show();
255        mKeyguardView.verifyUnlock();
256    }
257
258    /**
259     * A key has woken the device.  We use this to potentially adjust the state
260     * of the lock screen based on the key.
261     *
262     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
263     * Be sure not to take any action that takes a long time; any significant
264     * action should be posted to a handler.
265     *
266     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
267     * for a reason other than a key press.
268     */
269    public boolean wakeWhenReadyTq(int keyCode) {
270        if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
271        if (mKeyguardView != null) {
272            mKeyguardView.wakeWhenReadyTq(keyCode);
273            return true;
274        } else {
275            Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
276            return false;
277        }
278    }
279
280    /**
281     * Hides the keyguard view
282     */
283    public synchronized void hide() {
284        if (DEBUG) Log.d(TAG, "hide()");
285
286        if (mKeyguardHost != null) {
287            mKeyguardHost.setVisibility(View.GONE);
288            // Don't do this right away, so we can let the view continue to animate
289            // as it goes away.
290            if (mKeyguardView != null) {
291                final KeyguardViewBase lastView = mKeyguardView;
292                mKeyguardView = null;
293                mKeyguardHost.postDelayed(new Runnable() {
294                    public void run() {
295                        synchronized (KeyguardViewManager.this) {
296                            lastView.cleanUp();
297                            mKeyguardHost.removeView(lastView);
298                        }
299                    }
300                }, 500);
301            }
302        }
303    }
304
305    /**
306     * @return Whether the keyguard is showing
307     */
308    public synchronized boolean isShowing() {
309        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
310    }
311}
312