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