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