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