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.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, mUpdateMonitor, this); 161 mKeyguardView.setId(R.id.lock_screen); 162 mKeyguardView.setCallback(mCallback); 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 mKeyguardHost.setSystemUiVisibility(visFlags); 184 185 mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); 186 mKeyguardHost.setVisibility(View.VISIBLE); 187 mKeyguardView.requestFocus(); 188 } 189 190 public void setNeedsInput(boolean needsInput) { 191 mNeedsInput = needsInput; 192 if (mWindowLayoutParams != null) { 193 if (needsInput) { 194 mWindowLayoutParams.flags &= 195 ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 196 } else { 197 mWindowLayoutParams.flags |= 198 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 199 } 200 mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); 201 } 202 } 203 204 /** 205 * Reset the state of the view. 206 */ 207 public synchronized void reset() { 208 if (DEBUG) Log.d(TAG, "reset()"); 209 if (mKeyguardView != null) { 210 mKeyguardView.reset(); 211 } 212 } 213 214 public synchronized void onScreenTurnedOff() { 215 if (DEBUG) Log.d(TAG, "onScreenTurnedOff()"); 216 mScreenOn = false; 217 if (mKeyguardView != null) { 218 mKeyguardView.onScreenTurnedOff(); 219 } 220 } 221 222 public synchronized void onScreenTurnedOn( 223 final KeyguardViewManager.ShowListener showListener) { 224 if (DEBUG) Log.d(TAG, "onScreenTurnedOn()"); 225 mScreenOn = true; 226 if (mKeyguardView != null) { 227 mKeyguardView.onScreenTurnedOn(); 228 229 // Caller should wait for this window to be shown before turning 230 // on the screen. 231 if (mKeyguardHost.getVisibility() == View.VISIBLE) { 232 // Keyguard may be in the process of being shown, but not yet 233 // updated with the window manager... give it a chance to do so. 234 mKeyguardHost.post(new Runnable() { 235 @Override public void run() { 236 if (mKeyguardHost.getVisibility() == View.VISIBLE) { 237 showListener.onShown(mKeyguardHost.getWindowToken()); 238 } else { 239 showListener.onShown(null); 240 } 241 } 242 }); 243 } else { 244 showListener.onShown(null); 245 } 246 } else { 247 showListener.onShown(null); 248 } 249 } 250 251 public synchronized void verifyUnlock() { 252 if (DEBUG) Log.d(TAG, "verifyUnlock()"); 253 show(); 254 mKeyguardView.verifyUnlock(); 255 } 256 257 /** 258 * A key has woken the device. We use this to potentially adjust the state 259 * of the lock screen based on the key. 260 * 261 * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}. 262 * Be sure not to take any action that takes a long time; any significant 263 * action should be posted to a handler. 264 * 265 * @param keyCode The wake key. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking 266 * for a reason other than a key press. 267 */ 268 public boolean wakeWhenReadyTq(int keyCode) { 269 if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")"); 270 if (mKeyguardView != null) { 271 mKeyguardView.wakeWhenReadyTq(keyCode); 272 return true; 273 } else { 274 Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq"); 275 return false; 276 } 277 } 278 279 /** 280 * Hides the keyguard view 281 */ 282 public synchronized void hide() { 283 if (DEBUG) Log.d(TAG, "hide()"); 284 285 if (mKeyguardHost != null) { 286 mKeyguardHost.setVisibility(View.GONE); 287 // Don't do this right away, so we can let the view continue to animate 288 // as it goes away. 289 if (mKeyguardView != null) { 290 final KeyguardViewBase lastView = mKeyguardView; 291 mKeyguardView = null; 292 mKeyguardHost.postDelayed(new Runnable() { 293 public void run() { 294 synchronized (KeyguardViewManager.this) { 295 lastView.cleanUp(); 296 mKeyguardHost.removeView(lastView); 297 } 298 } 299 }, 500); 300 } 301 } 302 } 303 304 /** 305 * @return Whether the keyguard is showing 306 */ 307 public synchronized boolean isShowing() { 308 return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE); 309 } 310} 311