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