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_SLIPPERY 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.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY; 142 lp.setTitle("Keyguard"); 143 mWindowLayoutParams = lp; 144 145 mViewManager.addView(mKeyguardHost, lp); 146 } 147 148 if (enableScreenRotation) { 149 if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!"); 150 mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR; 151 } else { 152 if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!"); 153 mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 154 } 155 156 mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); 157 158 if (mKeyguardView == null) { 159 if (DEBUG) Log.d(TAG, "keyguard view is null, creating it..."); 160 mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mCallback, 161 mUpdateMonitor, this); 162 mKeyguardView.setId(R.id.lock_screen); 163 164 final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams( 165 ViewGroup.LayoutParams.MATCH_PARENT, 166 ViewGroup.LayoutParams.MATCH_PARENT); 167 168 mKeyguardHost.addView(mKeyguardView, lp); 169 170 if (mScreenOn) { 171 mKeyguardView.show(); 172 } 173 } 174 175 // Disable aspects of the system/status/navigation bars that are not appropriate or 176 // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities. 177 // Other disabled bits are handled by the KeyguardViewMediator talking directly to the 178 // status bar service. 179 int visFlags = 180 ( View.STATUS_BAR_DISABLE_BACK 181 | View.STATUS_BAR_DISABLE_HOME 182 ); 183 Log.v(TAG, "KGVM: Set visibility on " + mKeyguardHost + " to " + visFlags); 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