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