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