KeyguardViewManager.java revision 4284e9d19a3f917b85e5eac4d6e304fc9b866139
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_LAYOUT_IN_SCREEN
122                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
123            if (!mNeedsInput) {
124                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
125            }
126            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
127                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
128                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
129            }
130            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
131                    stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
132                    flags, PixelFormat.TRANSLUCENT);
133            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
134            lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
135            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
136                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
137                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
138                lp.privateFlags |=
139                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
140            }
141            lp.setTitle("Keyguard");
142            mWindowLayoutParams = lp;
143
144            mViewManager.addView(mKeyguardHost, lp);
145        }
146
147        if (enableScreenRotation) {
148            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
149            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
150        } else {
151            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
152            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
153        }
154
155        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
156
157        if (mKeyguardView == null) {
158            if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
159            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
160            mKeyguardView.setId(R.id.lock_screen);
161            mKeyguardView.setCallback(mCallback);
162
163            final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
164                    ViewGroup.LayoutParams.MATCH_PARENT,
165                    ViewGroup.LayoutParams.MATCH_PARENT);
166
167            mKeyguardHost.addView(mKeyguardView, lp);
168
169            if (mScreenOn) {
170                mKeyguardView.show();
171            }
172        }
173
174        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
175        mKeyguardHost.setVisibility(View.VISIBLE);
176        mKeyguardView.requestFocus();
177    }
178
179    public void setNeedsInput(boolean needsInput) {
180        mNeedsInput = needsInput;
181        if (mWindowLayoutParams != null) {
182            if (needsInput) {
183                mWindowLayoutParams.flags &=
184                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
185            } else {
186                mWindowLayoutParams.flags |=
187                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
188            }
189            mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
190        }
191    }
192
193    /**
194     * Reset the state of the view.
195     */
196    public synchronized void reset() {
197        if (DEBUG) Log.d(TAG, "reset()");
198        if (mKeyguardView != null) {
199            mKeyguardView.reset();
200        }
201    }
202
203    public synchronized void onScreenTurnedOff() {
204        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
205        mScreenOn = false;
206        if (mKeyguardView != null) {
207            mKeyguardView.onScreenTurnedOff();
208        }
209    }
210
211    public synchronized void onScreenTurnedOn(
212            final KeyguardViewManager.ShowListener showListener) {
213        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
214        mScreenOn = true;
215        if (mKeyguardView != null) {
216            mKeyguardView.onScreenTurnedOn();
217
218            // Caller should wait for this window to be shown before turning
219            // on the screen.
220            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
221                // Keyguard may be in the process of being shown, but not yet
222                // updated with the window manager...  give it a chance to do so.
223                mKeyguardHost.post(new Runnable() {
224                    @Override public void run() {
225                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
226                            showListener.onShown(mKeyguardHost.getWindowToken());
227                        } else {
228                            showListener.onShown(null);
229                        }
230                    }
231                });
232            } else {
233                showListener.onShown(null);
234            }
235        } else {
236            showListener.onShown(null);
237        }
238    }
239
240    public synchronized void verifyUnlock() {
241        if (DEBUG) Log.d(TAG, "verifyUnlock()");
242        show();
243        mKeyguardView.verifyUnlock();
244    }
245
246    /**
247     * A key has woken the device.  We use this to potentially adjust the state
248     * of the lock screen based on the key.
249     *
250     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
251     * Be sure not to take any action that takes a long time; any significant
252     * action should be posted to a handler.
253     *
254     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
255     * for a reason other than a key press.
256     */
257    public boolean wakeWhenReadyTq(int keyCode) {
258        if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
259        if (mKeyguardView != null) {
260            mKeyguardView.wakeWhenReadyTq(keyCode);
261            return true;
262        } else {
263            Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
264            return false;
265        }
266    }
267
268    /**
269     * Hides the keyguard view
270     */
271    public synchronized void hide() {
272        if (DEBUG) Log.d(TAG, "hide()");
273
274        if (mKeyguardHost != null) {
275            mKeyguardHost.setVisibility(View.GONE);
276            // Don't do this right away, so we can let the view continue to animate
277            // as it goes away.
278            if (mKeyguardView != null) {
279                final KeyguardViewBase lastView = mKeyguardView;
280                mKeyguardView = null;
281                mKeyguardHost.postDelayed(new Runnable() {
282                    public void run() {
283                        synchronized (KeyguardViewManager.this) {
284                            lastView.cleanUp();
285                            mKeyguardHost.removeView(lastView);
286                        }
287                    }
288                }, 500);
289            }
290        }
291    }
292
293    /**
294     * @return Whether the keyguard is showing
295     */
296    public synchronized boolean isShowing() {
297        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
298    }
299}
300