• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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