KeyguardServiceDelegate.java revision c0b676dcc23baedb12946c3470d9fa9b02cb39e0
1package com.android.internal.policy.impl.keyguard;
2
3import android.content.ComponentName;
4import android.content.Context;
5import android.content.Intent;
6import android.content.ServiceConnection;
7import android.content.pm.ActivityInfo;
8import android.graphics.PixelFormat;
9import android.os.Bundle;
10import android.os.IBinder;
11import android.os.RemoteException;
12import android.os.UserHandle;
13import android.util.Log;
14import android.util.Slog;
15import android.view.View;
16import android.view.ViewGroup;
17import android.view.WindowManager;
18import android.view.WindowManagerPolicy.OnKeyguardExitResult;
19
20import com.android.internal.policy.IKeyguardExitCallback;
21import com.android.internal.policy.IKeyguardShowCallback;
22import com.android.internal.policy.IKeyguardService;
23import com.android.internal.widget.LockPatternUtils;
24import com.android.internal.policy.impl.KeyguardServiceWrapper;
25
26/**
27 * A local class that keeps a cache of keyguard state that can be restored in the event
28 * keyguard crashes. It currently also allows runtime-selectable
29 * local or remote instances of keyguard.
30 */
31public class KeyguardServiceDelegate {
32    private static final String KEYGUARD_PACKAGE = "com.android.keyguard";
33    private static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
34    private static final String TAG = "KeyguardServiceDelegate";
35    private static final boolean DEBUG = true;
36    protected KeyguardServiceWrapper mKeyguardService;
37    private View mScrim; // shown if keyguard crashes
38    private KeyguardState mKeyguardState = new KeyguardState();
39
40    /* package */ static final class KeyguardState {
41        boolean showing;
42        boolean showingAndNotHidden;
43        boolean inputRestricted;
44        boolean hidden;
45        boolean secure;
46        boolean dreaming;
47        boolean systemIsReady;
48        public boolean enabled;
49        public boolean dismissable;
50        public int offReason;
51        public int currentUser;
52        public boolean screenIsOn;
53    };
54
55    public interface ShowListener {
56        public void onShown(IBinder windowToken);
57    }
58
59    // A delegate class to map a particular invocation with a ShowListener object.
60    private final class KeyguardShowDelegate extends IKeyguardShowCallback.Stub {
61        private ShowListener mShowListener;
62
63        KeyguardShowDelegate(ShowListener showListener) {
64            mShowListener = showListener;
65        }
66
67        @Override
68        public void onShown(IBinder windowToken) throws RemoteException {
69            if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****");
70            if (mShowListener != null) {
71                mShowListener.onShown(windowToken);
72            }
73            hideScrim();
74        }
75    };
76
77    // A delegate class to map a particular invocation with an OnKeyguardExitResult object.
78    private final class KeyguardExitDelegate extends IKeyguardExitCallback.Stub {
79        private OnKeyguardExitResult mOnKeyguardExitResult;
80
81        KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult) {
82            mOnKeyguardExitResult = onKeyguardExitResult;
83        }
84
85        @Override
86        public void onKeyguardExitResult(boolean success) throws RemoteException {
87            if (DEBUG) Log.v(TAG, "**** onKeyguardExitResult(" + success +") CALLED ****");
88            if (mOnKeyguardExitResult != null) {
89                mOnKeyguardExitResult.onKeyguardExitResult(success);
90            }
91        }
92    };
93
94    public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
95        Intent intent = new Intent();
96        intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
97        mScrim = createScrim(context);
98        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
99                Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
100            if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
101        } else {
102            if (DEBUG) Log.v(TAG, "*** Keyguard started");
103        }
104    }
105
106    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
107        @Override
108        public void onServiceConnected(ComponentName name, IBinder service) {
109            if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
110            mKeyguardService = new KeyguardServiceWrapper(
111                    IKeyguardService.Stub.asInterface(service));
112            if (mKeyguardState.systemIsReady) {
113                // If the system is ready, it means keyguard crashed and restarted.
114                mKeyguardService.onSystemReady();
115                // This is used to hide the scrim once keyguard displays.
116                mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
117            }
118        }
119
120        @Override
121        public void onServiceDisconnected(ComponentName name) {
122            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
123            mKeyguardService = null;
124        }
125
126    };
127
128    public boolean isShowing() {
129        if (mKeyguardService != null) {
130            mKeyguardState.showing = mKeyguardService.isShowing();
131        }
132        return mKeyguardState.showing;
133    }
134
135    public boolean isShowingAndNotHidden() {
136        if (mKeyguardService != null) {
137            mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden();
138        }
139        return mKeyguardState.showingAndNotHidden;
140    }
141
142    public boolean isInputRestricted() {
143        if (mKeyguardService != null) {
144            mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted();
145        }
146        return mKeyguardState.inputRestricted;
147    }
148
149    public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) {
150        if (mKeyguardService != null) {
151            mKeyguardService.verifyUnlock(new KeyguardExitDelegate(onKeyguardExitResult));
152        }
153    }
154
155    public void keyguardDone(boolean authenticated, boolean wakeup) {
156        if (mKeyguardService != null) {
157            mKeyguardService.keyguardDone(authenticated, wakeup);
158        }
159    }
160
161    public void setHidden(boolean isHidden) {
162        if (mKeyguardService != null) {
163            mKeyguardService.setHidden(isHidden);
164        }
165        mKeyguardState.hidden = isHidden;
166    }
167
168    public void dismiss() {
169        if (mKeyguardService != null) {
170            mKeyguardService.dismiss();
171        }
172    }
173
174    public boolean isSecure() {
175        if (mKeyguardService != null) {
176            mKeyguardState.secure = mKeyguardService.isSecure();
177        }
178        return mKeyguardState.secure;
179    }
180
181    public void onWakeKeyWhenKeyguardShowingTq(int keycodePower) {
182        if (mKeyguardService != null) {
183            mKeyguardService.onWakeKeyWhenKeyguardShowing(keycodePower);
184        }
185    }
186
187    public void onWakeMotionWhenKeyguardShowing() {
188        if (mKeyguardService != null) {
189            mKeyguardService.onWakeMotionWhenKeyguardShowing();
190        }
191    }
192
193    public void onDreamingStarted() {
194        if (mKeyguardService != null) {
195            mKeyguardService.onDreamingStarted();
196        }
197        mKeyguardState.dreaming = true;
198    }
199
200    public void onDreamingStopped() {
201        if (mKeyguardService != null) {
202            mKeyguardService.onDreamingStopped();
203        }
204        mKeyguardState.dreaming = false;
205    }
206
207    public void onScreenTurnedOn(final ShowListener showListener) {
208        if (mKeyguardService != null) {
209            if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + showListener + ")");
210            mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(showListener));
211        } else {
212            // try again when we establish a connection
213            Slog.w(TAG, "onScreenTurnedOn(): no keyguard service!");
214            // This shouldn't happen, but if it does, invoke the listener immediately
215            // to avoid a dark screen...
216            showListener.onShown(null);
217        }
218        mKeyguardState.screenIsOn = true;
219    }
220
221    public void onScreenTurnedOff(int why) {
222        if (mKeyguardService != null) {
223            mKeyguardService.onScreenTurnedOff(why);
224        }
225        mKeyguardState.offReason = why;
226        mKeyguardState.screenIsOn = false;
227    }
228
229    public void setKeyguardEnabled(boolean enabled) {
230        if (mKeyguardService != null) {
231            mKeyguardService.setKeyguardEnabled(enabled);
232        }
233        mKeyguardState.enabled = enabled;
234    }
235
236    public boolean isDismissable() {
237        if (mKeyguardService != null) {
238            mKeyguardState.dismissable = mKeyguardService.isDismissable();
239        }
240        return mKeyguardState.dismissable;
241    }
242
243    public void onSystemReady() {
244        if (mKeyguardService != null) {
245            mKeyguardService.onSystemReady();
246        } else {
247            if (DEBUG) Log.v(TAG, "onSystemReady() called before keyguard service was ready");
248            mKeyguardState.systemIsReady = true;
249        }
250    }
251
252    public void doKeyguardTimeout(Bundle options) {
253        if (mKeyguardService != null) {
254            mKeyguardService.doKeyguardTimeout(options);
255        }
256    }
257
258    public void showAssistant() {
259        if (mKeyguardService != null) {
260            mKeyguardService.showAssistant();
261        }
262    }
263
264    public void setCurrentUser(int newUserId) {
265        if (mKeyguardService != null) {
266            mKeyguardService.setCurrentUser(newUserId);
267        }
268        mKeyguardState.currentUser = newUserId;
269    }
270
271    private static final View createScrim(Context context) {
272        View view = new View(context);
273
274        int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
275                | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
276                | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
277                | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
278                ;
279
280        final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
281        final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
282        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
283                stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
284        lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
285        lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
286        lp.setTitle("KeyguardScrim");
287        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
288        wm.addView(view, lp);
289        view.setVisibility(View.GONE);
290        // Disable pretty much everything in statusbar until keyguard comes back and we know
291        // the state of the world.
292        view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME
293                | View.STATUS_BAR_DISABLE_BACK
294                | View.STATUS_BAR_DISABLE_RECENT
295                | View.STATUS_BAR_DISABLE_EXPAND
296                | View.STATUS_BAR_DISABLE_SEARCH);
297        return view;
298    }
299
300    public void showScrim() {
301        mScrim.post(new Runnable() {
302            @Override
303            public void run() {
304                mScrim.setVisibility(View.VISIBLE);
305            }
306        });
307    }
308
309    public void hideScrim() {
310        mScrim.post(new Runnable() {
311            @Override
312            public void run() {
313                mScrim.setVisibility(View.GONE);
314            }
315        });
316    }
317
318}
319