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