KeyguardServiceDelegate.java revision d88eb2693b6a70af0f5fbc5881ce855e28de33aa
1package com.android.server.policy.keyguard; 2 3import android.content.ComponentName; 4import android.content.Context; 5import android.content.Intent; 6import android.content.ServiceConnection; 7import android.content.pm.ActivityInfo; 8import android.content.res.Resources; 9import android.graphics.PixelFormat; 10import android.os.Bundle; 11import android.os.Handler; 12import android.os.IBinder; 13import android.os.RemoteException; 14import android.os.UserHandle; 15import android.util.Log; 16import android.util.Slog; 17import android.view.View; 18import android.view.ViewGroup; 19import android.view.WindowManager; 20import android.view.WindowManagerPolicy.OnKeyguardExitResult; 21 22import com.android.internal.policy.IKeyguardDrawnCallback; 23import com.android.internal.policy.IKeyguardExitCallback; 24import com.android.internal.policy.IKeyguardService; 25import com.android.server.UiThread; 26 27import java.io.PrintWriter; 28 29/** 30 * A local class that keeps a cache of keyguard state that can be restored in the event 31 * keyguard crashes. It currently also allows runtime-selectable 32 * local or remote instances of keyguard. 33 */ 34public class KeyguardServiceDelegate { 35 private static final String TAG = "KeyguardServiceDelegate"; 36 private static final boolean DEBUG = true; 37 38 private static final int SCREEN_STATE_OFF = 0; 39 private static final int SCREEN_STATE_TURNING_ON = 1; 40 private static final int SCREEN_STATE_ON = 2; 41 42 private static final int INTERACTIVE_STATE_SLEEP = 0; 43 private static final int INTERACTIVE_STATE_AWAKE = 1; 44 private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 2; 45 46 protected KeyguardServiceWrapper mKeyguardService; 47 private final Context mContext; 48 private final View mScrim; // shown if keyguard crashes 49 private final Handler mScrimHandler; 50 private final KeyguardState mKeyguardState = new KeyguardState(); 51 private DrawnListener mDrawnListenerWhenConnect; 52 53 private static final class KeyguardState { 54 KeyguardState() { 55 // Assume keyguard is showing and secure until we know for sure. This is here in 56 // the event something checks before the service is actually started. 57 // KeyguardService itself should default to this state until the real state is known. 58 showing = true; 59 showingAndNotOccluded = true; 60 secure = true; 61 deviceHasKeyguard = true; 62 } 63 boolean showing; 64 boolean showingAndNotOccluded; 65 boolean inputRestricted; 66 boolean occluded; 67 boolean secure; 68 boolean dreaming; 69 boolean systemIsReady; 70 boolean deviceHasKeyguard; 71 public boolean enabled; 72 public int offReason; 73 public int currentUser; 74 public boolean bootCompleted; 75 public int screenState; 76 public int interactiveState; 77 }; 78 79 public interface DrawnListener { 80 void onDrawn(); 81 } 82 83 // A delegate class to map a particular invocation with a ShowListener object. 84 private final class KeyguardShowDelegate extends IKeyguardDrawnCallback.Stub { 85 private DrawnListener mDrawnListener; 86 87 KeyguardShowDelegate(DrawnListener drawnListener) { 88 mDrawnListener = drawnListener; 89 } 90 91 @Override 92 public void onDrawn() throws RemoteException { 93 if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****"); 94 if (mDrawnListener != null) { 95 mDrawnListener.onDrawn(); 96 } 97 hideScrim(); 98 } 99 }; 100 101 // A delegate class to map a particular invocation with an OnKeyguardExitResult object. 102 private final class KeyguardExitDelegate extends IKeyguardExitCallback.Stub { 103 private OnKeyguardExitResult mOnKeyguardExitResult; 104 105 KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult) { 106 mOnKeyguardExitResult = onKeyguardExitResult; 107 } 108 109 @Override 110 public void onKeyguardExitResult(boolean success) throws RemoteException { 111 if (DEBUG) Log.v(TAG, "**** onKeyguardExitResult(" + success +") CALLED ****"); 112 if (mOnKeyguardExitResult != null) { 113 mOnKeyguardExitResult.onKeyguardExitResult(success); 114 } 115 } 116 }; 117 118 public KeyguardServiceDelegate(Context context) { 119 mContext = context; 120 mScrimHandler = UiThread.getHandler(); 121 mScrim = createScrim(context, mScrimHandler); 122 } 123 124 public void bindService(Context context) { 125 Intent intent = new Intent(); 126 final Resources resources = context.getApplicationContext().getResources(); 127 128 final ComponentName keyguardComponent = ComponentName.unflattenFromString( 129 resources.getString(com.android.internal.R.string.config_keyguardComponent)); 130 intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); 131 intent.setComponent(keyguardComponent); 132 133 if (!context.bindServiceAsUser(intent, mKeyguardConnection, 134 Context.BIND_AUTO_CREATE, mScrimHandler, UserHandle.SYSTEM)) { 135 Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent); 136 mKeyguardState.showing = false; 137 mKeyguardState.showingAndNotOccluded = false; 138 mKeyguardState.secure = false; 139 synchronized (mKeyguardState) { 140 // TODO: Fix synchronisation model in this class. The other state in this class 141 // is at least self-healing but a race condition here can lead to the scrim being 142 // stuck on keyguard-less devices. 143 mKeyguardState.deviceHasKeyguard = false; 144 hideScrim(); 145 } 146 } else { 147 if (DEBUG) Log.v(TAG, "*** Keyguard started"); 148 } 149 } 150 151 private final ServiceConnection mKeyguardConnection = new ServiceConnection() { 152 @Override 153 public void onServiceConnected(ComponentName name, IBinder service) { 154 if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)"); 155 mKeyguardService = new KeyguardServiceWrapper(mContext, 156 IKeyguardService.Stub.asInterface(service)); 157 if (mKeyguardState.systemIsReady) { 158 // If the system is ready, it means keyguard crashed and restarted. 159 mKeyguardService.onSystemReady(); 160 // This is used to hide the scrim once keyguard displays. 161 if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) { 162 mKeyguardService.onStartedWakingUp(); 163 } 164 if (mKeyguardState.screenState == SCREEN_STATE_ON 165 || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) { 166 mKeyguardService.onScreenTurningOn( 167 new KeyguardShowDelegate(mDrawnListenerWhenConnect)); 168 } 169 if (mKeyguardState.screenState == SCREEN_STATE_ON) { 170 mKeyguardService.onScreenTurnedOn(); 171 } 172 mDrawnListenerWhenConnect = null; 173 } 174 if (mKeyguardState.bootCompleted) { 175 mKeyguardService.onBootCompleted(); 176 } 177 if (mKeyguardState.occluded) { 178 mKeyguardService.setOccluded(mKeyguardState.occluded); 179 } 180 } 181 182 @Override 183 public void onServiceDisconnected(ComponentName name) { 184 if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)"); 185 mKeyguardService = null; 186 } 187 188 }; 189 190 public boolean isShowing() { 191 if (mKeyguardService != null) { 192 mKeyguardState.showing = mKeyguardService.isShowing(); 193 } 194 return mKeyguardState.showing; 195 } 196 197 public boolean isTrusted() { 198 if (mKeyguardService != null) { 199 return mKeyguardService.isTrusted(); 200 } 201 return false; 202 } 203 204 public boolean isInputRestricted() { 205 if (mKeyguardService != null) { 206 mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted(); 207 } 208 return mKeyguardState.inputRestricted; 209 } 210 211 public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) { 212 if (mKeyguardService != null) { 213 mKeyguardService.verifyUnlock(new KeyguardExitDelegate(onKeyguardExitResult)); 214 } 215 } 216 217 public void keyguardDone(boolean authenticated, boolean wakeup) { 218 if (mKeyguardService != null) { 219 mKeyguardService.keyguardDone(authenticated, wakeup); 220 } 221 } 222 223 public void setOccluded(boolean isOccluded) { 224 if (mKeyguardService != null) { 225 if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ")"); 226 mKeyguardService.setOccluded(isOccluded); 227 } 228 mKeyguardState.occluded = isOccluded; 229 } 230 231 public void dismiss(boolean allowWhileOccluded) { 232 if (mKeyguardService != null) { 233 mKeyguardService.dismiss(allowWhileOccluded); 234 } 235 } 236 237 public boolean isSecure(int userId) { 238 if (mKeyguardService != null) { 239 mKeyguardState.secure = mKeyguardService.isSecure(userId); 240 } 241 return mKeyguardState.secure; 242 } 243 244 public void onDreamingStarted() { 245 if (mKeyguardService != null) { 246 mKeyguardService.onDreamingStarted(); 247 } 248 mKeyguardState.dreaming = true; 249 } 250 251 public void onDreamingStopped() { 252 if (mKeyguardService != null) { 253 mKeyguardService.onDreamingStopped(); 254 } 255 mKeyguardState.dreaming = false; 256 } 257 258 public void onStartedWakingUp() { 259 if (mKeyguardService != null) { 260 if (DEBUG) Log.v(TAG, "onStartedWakingUp()"); 261 mKeyguardService.onStartedWakingUp(); 262 } 263 mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE; 264 } 265 266 public void onScreenTurnedOff() { 267 if (mKeyguardService != null) { 268 if (DEBUG) Log.v(TAG, "onScreenTurnedOff()"); 269 mKeyguardService.onScreenTurnedOff(); 270 } 271 mKeyguardState.screenState = SCREEN_STATE_OFF; 272 } 273 274 public void onScreenTurningOn(final DrawnListener drawnListener) { 275 if (mKeyguardService != null) { 276 if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + drawnListener + ")"); 277 mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener)); 278 } else { 279 // try again when we establish a connection 280 Slog.w(TAG, "onScreenTurningOn(): no keyguard service!"); 281 // This shouldn't happen, but if it does, show the scrim immediately and 282 // invoke the listener's callback after the service actually connects. 283 mDrawnListenerWhenConnect = drawnListener; 284 showScrim(); 285 } 286 mKeyguardState.screenState = SCREEN_STATE_TURNING_ON; 287 } 288 289 public void onScreenTurnedOn() { 290 if (mKeyguardService != null) { 291 if (DEBUG) Log.v(TAG, "onScreenTurnedOn()"); 292 mKeyguardService.onScreenTurnedOn(); 293 } 294 mKeyguardState.screenState = SCREEN_STATE_ON; 295 } 296 297 public void onStartedGoingToSleep(int why) { 298 if (mKeyguardService != null) { 299 mKeyguardService.onStartedGoingToSleep(why); 300 } 301 mKeyguardState.offReason = why; 302 mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP; 303 } 304 305 public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) { 306 if (mKeyguardService != null) { 307 mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered); 308 } 309 mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP; 310 } 311 312 public void setKeyguardEnabled(boolean enabled) { 313 if (mKeyguardService != null) { 314 mKeyguardService.setKeyguardEnabled(enabled); 315 } 316 mKeyguardState.enabled = enabled; 317 } 318 319 public void onSystemReady() { 320 if (mKeyguardService != null) { 321 mKeyguardService.onSystemReady(); 322 } else { 323 mKeyguardState.systemIsReady = true; 324 } 325 } 326 327 public void doKeyguardTimeout(Bundle options) { 328 if (mKeyguardService != null) { 329 mKeyguardService.doKeyguardTimeout(options); 330 } 331 } 332 333 public void setCurrentUser(int newUserId) { 334 if (mKeyguardService != null) { 335 mKeyguardService.setCurrentUser(newUserId); 336 } 337 mKeyguardState.currentUser = newUserId; 338 } 339 340 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 341 if (mKeyguardService != null) { 342 mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration); 343 } 344 } 345 346 private static View createScrim(Context context, Handler handler) { 347 final View view = new View(context); 348 349 int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 350 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR 351 | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN 352 | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER 353 ; 354 355 final int stretch = ViewGroup.LayoutParams.MATCH_PARENT; 356 final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM; 357 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 358 stretch, stretch, type, flags, PixelFormat.TRANSLUCENT); 359 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 360 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 361 lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 362 lp.setTitle("KeyguardScrim"); 363 final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 364 // Disable pretty much everything in statusbar until keyguard comes back and we know 365 // the state of the world. 366 view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME 367 | View.STATUS_BAR_DISABLE_BACK 368 | View.STATUS_BAR_DISABLE_RECENT 369 | View.STATUS_BAR_DISABLE_EXPAND 370 | View.STATUS_BAR_DISABLE_SEARCH); 371 handler.post(new Runnable() { 372 @Override 373 public void run() { 374 wm.addView(view, lp); 375 } 376 }); 377 return view; 378 } 379 380 public void showScrim() { 381 synchronized (mKeyguardState) { 382 if (!mKeyguardState.deviceHasKeyguard) return; 383 mScrimHandler.post(new Runnable() { 384 @Override 385 public void run() { 386 mScrim.setVisibility(View.VISIBLE); 387 } 388 }); 389 } 390 } 391 392 public void hideScrim() { 393 mScrimHandler.post(new Runnable() { 394 @Override 395 public void run() { 396 mScrim.setVisibility(View.GONE); 397 } 398 }); 399 } 400 401 public void onBootCompleted() { 402 if (mKeyguardService != null) { 403 mKeyguardService.onBootCompleted(); 404 } 405 mKeyguardState.bootCompleted = true; 406 } 407 408 public void onActivityDrawn() { 409 if (mKeyguardService != null) { 410 mKeyguardService.onActivityDrawn(); 411 } 412 } 413 414 public void dump(String prefix, PrintWriter pw) { 415 pw.println(prefix + TAG); 416 prefix += " "; 417 pw.println(prefix + "showing=" + mKeyguardState.showing); 418 pw.println(prefix + "showingAndNotOccluded=" + mKeyguardState.showingAndNotOccluded); 419 pw.println(prefix + "inputRestricted=" + mKeyguardState.inputRestricted); 420 pw.println(prefix + "occluded=" + mKeyguardState.occluded); 421 pw.println(prefix + "secure=" + mKeyguardState.secure); 422 pw.println(prefix + "dreaming=" + mKeyguardState.dreaming); 423 pw.println(prefix + "systemIsReady=" + mKeyguardState.systemIsReady); 424 pw.println(prefix + "deviceHasKeyguard=" + mKeyguardState.deviceHasKeyguard); 425 pw.println(prefix + "enabled=" + mKeyguardState.enabled); 426 pw.println(prefix + "offReason=" + mKeyguardState.offReason); 427 pw.println(prefix + "currentUser=" + mKeyguardState.currentUser); 428 pw.println(prefix + "bootCompleted=" + mKeyguardState.bootCompleted); 429 pw.println(prefix + "screenState=" + mKeyguardState.screenState); 430 pw.println(prefix + "interactiveState=" + mKeyguardState.interactiveState); 431 if (mKeyguardService != null) { 432 mKeyguardService.dump(prefix, pw); 433 } 434 } 435} 436