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 } 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 { onDrawn()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 KeyguardShowDelegate(DrawnListener drawnListener)87 KeyguardShowDelegate(DrawnListener drawnListener) { 88 mDrawnListener = drawnListener; 89 } 90 91 @Override onDrawn()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 KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult)105 KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult) { 106 mOnKeyguardExitResult = onKeyguardExitResult; 107 } 108 109 @Override onKeyguardExitResult(boolean success)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 KeyguardServiceDelegate(Context context)118 public KeyguardServiceDelegate(Context context) { 119 mContext = context; 120 mScrimHandler = UiThread.getHandler(); 121 mScrim = createScrim(context, mScrimHandler); 122 } 123 bindService(Context context)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 isShowing()190 public boolean isShowing() { 191 if (mKeyguardService != null) { 192 mKeyguardState.showing = mKeyguardService.isShowing(); 193 } 194 return mKeyguardState.showing; 195 } 196 isInputRestricted()197 public boolean isInputRestricted() { 198 if (mKeyguardService != null) { 199 mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted(); 200 } 201 return mKeyguardState.inputRestricted; 202 } 203 verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult)204 public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) { 205 if (mKeyguardService != null) { 206 mKeyguardService.verifyUnlock(new KeyguardExitDelegate(onKeyguardExitResult)); 207 } 208 } 209 keyguardDone(boolean authenticated, boolean wakeup)210 public void keyguardDone(boolean authenticated, boolean wakeup) { 211 if (mKeyguardService != null) { 212 mKeyguardService.keyguardDone(authenticated, wakeup); 213 } 214 } 215 setOccluded(boolean isOccluded)216 public void setOccluded(boolean isOccluded) { 217 if (mKeyguardService != null) { 218 mKeyguardService.setOccluded(isOccluded); 219 } 220 mKeyguardState.occluded = isOccluded; 221 } 222 dismiss()223 public void dismiss() { 224 if (mKeyguardService != null) { 225 mKeyguardService.dismiss(); 226 } 227 } 228 isSecure(int userId)229 public boolean isSecure(int userId) { 230 if (mKeyguardService != null) { 231 mKeyguardState.secure = mKeyguardService.isSecure(userId); 232 } 233 return mKeyguardState.secure; 234 } 235 onDreamingStarted()236 public void onDreamingStarted() { 237 if (mKeyguardService != null) { 238 mKeyguardService.onDreamingStarted(); 239 } 240 mKeyguardState.dreaming = true; 241 } 242 onDreamingStopped()243 public void onDreamingStopped() { 244 if (mKeyguardService != null) { 245 mKeyguardService.onDreamingStopped(); 246 } 247 mKeyguardState.dreaming = false; 248 } 249 onStartedWakingUp()250 public void onStartedWakingUp() { 251 if (mKeyguardService != null) { 252 if (DEBUG) Log.v(TAG, "onStartedWakingUp()"); 253 mKeyguardService.onStartedWakingUp(); 254 } 255 mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE; 256 } 257 onScreenTurnedOff()258 public void onScreenTurnedOff() { 259 if (mKeyguardService != null) { 260 if (DEBUG) Log.v(TAG, "onScreenTurnedOff()"); 261 mKeyguardService.onScreenTurnedOff(); 262 } 263 mKeyguardState.screenState = SCREEN_STATE_OFF; 264 } 265 onScreenTurningOn(final DrawnListener drawnListener)266 public void onScreenTurningOn(final DrawnListener drawnListener) { 267 if (mKeyguardService != null) { 268 if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + drawnListener + ")"); 269 mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener)); 270 } else { 271 // try again when we establish a connection 272 Slog.w(TAG, "onScreenTurningOn(): no keyguard service!"); 273 // This shouldn't happen, but if it does, show the scrim immediately and 274 // invoke the listener's callback after the service actually connects. 275 mDrawnListenerWhenConnect = drawnListener; 276 showScrim(); 277 } 278 mKeyguardState.screenState = SCREEN_STATE_TURNING_ON; 279 } 280 onScreenTurnedOn()281 public void onScreenTurnedOn() { 282 if (mKeyguardService != null) { 283 if (DEBUG) Log.v(TAG, "onScreenTurnedOn()"); 284 mKeyguardService.onScreenTurnedOn(); 285 } 286 mKeyguardState.screenState = SCREEN_STATE_ON; 287 } 288 onStartedGoingToSleep(int why)289 public void onStartedGoingToSleep(int why) { 290 if (mKeyguardService != null) { 291 mKeyguardService.onStartedGoingToSleep(why); 292 } 293 mKeyguardState.offReason = why; 294 mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP; 295 } 296 onFinishedGoingToSleep(int why, boolean cameraGestureTriggered)297 public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) { 298 if (mKeyguardService != null) { 299 mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered); 300 } 301 mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP; 302 } 303 setKeyguardEnabled(boolean enabled)304 public void setKeyguardEnabled(boolean enabled) { 305 if (mKeyguardService != null) { 306 mKeyguardService.setKeyguardEnabled(enabled); 307 } 308 mKeyguardState.enabled = enabled; 309 } 310 onSystemReady()311 public void onSystemReady() { 312 if (mKeyguardService != null) { 313 mKeyguardService.onSystemReady(); 314 } else { 315 mKeyguardState.systemIsReady = true; 316 } 317 } 318 doKeyguardTimeout(Bundle options)319 public void doKeyguardTimeout(Bundle options) { 320 if (mKeyguardService != null) { 321 mKeyguardService.doKeyguardTimeout(options); 322 } 323 } 324 setCurrentUser(int newUserId)325 public void setCurrentUser(int newUserId) { 326 if (mKeyguardService != null) { 327 mKeyguardService.setCurrentUser(newUserId); 328 } 329 mKeyguardState.currentUser = newUserId; 330 } 331 startKeyguardExitAnimation(long startTime, long fadeoutDuration)332 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 333 if (mKeyguardService != null) { 334 mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration); 335 } 336 } 337 createScrim(Context context, Handler handler)338 private static View createScrim(Context context, Handler handler) { 339 final View view = new View(context); 340 341 int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 342 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR 343 | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN 344 | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER 345 ; 346 347 final int stretch = ViewGroup.LayoutParams.MATCH_PARENT; 348 final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM; 349 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 350 stretch, stretch, type, flags, PixelFormat.TRANSLUCENT); 351 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 352 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 353 lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 354 lp.setTitle("KeyguardScrim"); 355 final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 356 // Disable pretty much everything in statusbar until keyguard comes back and we know 357 // the state of the world. 358 view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME 359 | View.STATUS_BAR_DISABLE_BACK 360 | View.STATUS_BAR_DISABLE_RECENT 361 | View.STATUS_BAR_DISABLE_EXPAND 362 | View.STATUS_BAR_DISABLE_SEARCH); 363 handler.post(new Runnable() { 364 @Override 365 public void run() { 366 wm.addView(view, lp); 367 } 368 }); 369 return view; 370 } 371 showScrim()372 public void showScrim() { 373 synchronized (mKeyguardState) { 374 if (!mKeyguardState.deviceHasKeyguard) return; 375 mScrimHandler.post(new Runnable() { 376 @Override 377 public void run() { 378 mScrim.setVisibility(View.VISIBLE); 379 } 380 }); 381 } 382 } 383 hideScrim()384 public void hideScrim() { 385 mScrimHandler.post(new Runnable() { 386 @Override 387 public void run() { 388 mScrim.setVisibility(View.GONE); 389 } 390 }); 391 } 392 onBootCompleted()393 public void onBootCompleted() { 394 if (mKeyguardService != null) { 395 mKeyguardService.onBootCompleted(); 396 } 397 mKeyguardState.bootCompleted = true; 398 } 399 onActivityDrawn()400 public void onActivityDrawn() { 401 if (mKeyguardService != null) { 402 mKeyguardService.onActivityDrawn(); 403 } 404 } 405 dump(String prefix, PrintWriter pw)406 public void dump(String prefix, PrintWriter pw) { 407 pw.println(prefix + TAG); 408 prefix += " "; 409 pw.println(prefix + "showing=" + mKeyguardState.showing); 410 pw.println(prefix + "showingAndNotOccluded=" + mKeyguardState.showingAndNotOccluded); 411 pw.println(prefix + "inputRestricted=" + mKeyguardState.inputRestricted); 412 pw.println(prefix + "occluded=" + mKeyguardState.occluded); 413 pw.println(prefix + "secure=" + mKeyguardState.secure); 414 pw.println(prefix + "dreaming=" + mKeyguardState.dreaming); 415 pw.println(prefix + "systemIsReady=" + mKeyguardState.systemIsReady); 416 pw.println(prefix + "deviceHasKeyguard=" + mKeyguardState.deviceHasKeyguard); 417 pw.println(prefix + "enabled=" + mKeyguardState.enabled); 418 pw.println(prefix + "offReason=" + mKeyguardState.offReason); 419 pw.println(prefix + "currentUser=" + mKeyguardState.currentUser); 420 pw.println(prefix + "bootCompleted=" + mKeyguardState.bootCompleted); 421 pw.println(prefix + "screenState=" + mKeyguardState.screenState); 422 pw.println(prefix + "interactiveState=" + mKeyguardState.interactiveState); 423 if (mKeyguardService != null) { 424 mKeyguardService.dump(prefix, pw); 425 } 426 } 427 } 428