KeyguardManager.java revision e256a18dcd8c0fda68abc5005c405eb8a5c18bea
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import android.Manifest;
20import android.annotation.RequiresPermission;
21import android.app.trust.ITrustManager;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
26import android.os.Binder;
27import android.os.IBinder;
28import android.os.IUserManager;
29import android.os.RemoteException;
30import android.os.ServiceManager;
31import android.os.UserHandle;
32import android.view.IOnKeyguardExitResult;
33import android.view.IWindowManager;
34import android.view.WindowManagerGlobal;
35
36import java.util.List;
37
38/**
39 * Class that can be used to lock and unlock the keyboard. Get an instance of this
40 * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
41 * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
42 * actual class to control the keyboard locking is
43 * {@link android.app.KeyguardManager.KeyguardLock}.
44 */
45public class KeyguardManager {
46    private IWindowManager mWM;
47    private ITrustManager mTrustManager;
48    private IUserManager mUserManager;
49    private Context mContext;
50
51    /**
52     * Intent used to prompt user for device credentials.
53     * @hide
54     */
55    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL =
56            "android.app.action.CONFIRM_DEVICE_CREDENTIAL";
57
58    /**
59     * Intent used to prompt user for device credentials.
60     * @hide
61     */
62    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER =
63            "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER";
64
65    /**
66     * A CharSequence dialog title to show to the user when used with a
67     * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
68     * @hide
69     */
70    public static final String EXTRA_TITLE = "android.app.extra.TITLE";
71
72    /**
73     * A CharSequence description to show to the user when used with
74     * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
75     * @hide
76     */
77    public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION";
78
79    /**
80     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
81     * for the current user of the device. The caller is expected to launch this activity using
82     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
83     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
84     *
85     * @return the intent for launching the activity or null if no password is required.
86     **/
87    public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
88        if (!isDeviceSecure()) return null;
89        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
90        intent.putExtra(EXTRA_TITLE, title);
91        intent.putExtra(EXTRA_DESCRIPTION, description);
92
93        // explicitly set the package for security
94        intent.setPackage(getSettingsPackageForIntent(intent));
95        return intent;
96    }
97
98    /**
99     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
100     * for the given user. The caller is expected to launch this activity using
101     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
102     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
103     *
104     * @return the intent for launching the activity or null if no password is required.
105     *
106     * @hide
107     */
108    public Intent createConfirmDeviceCredentialIntent(
109            CharSequence title, CharSequence description, int userId) {
110        if (!isDeviceSecure(userId)) return null;
111        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
112        intent.putExtra(EXTRA_TITLE, title);
113        intent.putExtra(EXTRA_DESCRIPTION, description);
114        intent.putExtra(Intent.EXTRA_USER_ID, userId);
115
116        // explicitly set the package for security
117        intent.setPackage(getSettingsPackageForIntent(intent));
118
119        return intent;
120    }
121
122    private String getSettingsPackageForIntent(Intent intent) {
123        List<ResolveInfo> resolveInfos = mContext.getPackageManager()
124                .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY);
125        for (int i = 0; i < resolveInfos.size(); i++) {
126            return resolveInfos.get(i).activityInfo.packageName;
127        }
128
129        return "com.android.settings";
130    }
131
132    /**
133     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
134     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
135     * instead; this allows you to seamlessly hide the keyguard as your application
136     * moves in and out of the foreground and does not require that any special
137     * permissions be requested.
138     *
139     * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows
140     * you to disable / reenable the keyguard.
141     */
142    public class KeyguardLock {
143        private final IBinder mToken = new Binder();
144        private final String mTag;
145
146        KeyguardLock(String tag) {
147            mTag = tag;
148        }
149
150        /**
151         * Disable the keyguard from showing.  If the keyguard is currently
152         * showing, hide it.  The keyguard will be prevented from showing again
153         * until {@link #reenableKeyguard()} is called.
154         *
155         * A good place to call this is from {@link android.app.Activity#onResume()}
156         *
157         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager}
158         * is enabled that requires a password.
159         *
160         * <p>This method requires the caller to hold the permission
161         * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
162         *
163         * @see #reenableKeyguard()
164         */
165        @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
166        public void disableKeyguard() {
167            try {
168                mWM.disableKeyguard(mToken, mTag);
169            } catch (RemoteException ex) {
170            }
171        }
172
173        /**
174         * Reenable the keyguard.  The keyguard will reappear if the previous
175         * call to {@link #disableKeyguard()} caused it to be hidden.
176         *
177         * A good place to call this is from {@link android.app.Activity#onPause()}
178         *
179         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager}
180         * is enabled that requires a password.
181         *
182         * <p>This method requires the caller to hold the permission
183         * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
184         *
185         * @see #disableKeyguard()
186         */
187        @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
188        public void reenableKeyguard() {
189            try {
190                mWM.reenableKeyguard(mToken);
191            } catch (RemoteException ex) {
192            }
193        }
194    }
195
196    /**
197     * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify
198     * caller of result.
199     */
200    public interface OnKeyguardExitResult {
201
202        /**
203         * @param success True if the user was able to authenticate, false if
204         *   not.
205         */
206        void onKeyguardExitResult(boolean success);
207    }
208
209
210    KeyguardManager(Context context) {
211        mContext = context;
212        mWM = WindowManagerGlobal.getWindowManagerService();
213        mTrustManager = ITrustManager.Stub.asInterface(
214                ServiceManager.getService(Context.TRUST_SERVICE));
215        mUserManager = IUserManager.Stub.asInterface(
216                ServiceManager.getService(Context.USER_SERVICE));
217    }
218
219    /**
220     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
221     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
222     * instead; this allows you to seamlessly hide the keyguard as your application
223     * moves in and out of the foreground and does not require that any special
224     * permissions be requested.
225     *
226     * Enables you to lock or unlock the keyboard. Get an instance of this class by
227     * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
228     * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}.
229     * @param tag A tag that informally identifies who you are (for debugging who
230     *   is disabling he keyguard).
231     *
232     * @return A {@link KeyguardLock} handle to use to disable and reenable the
233     *   keyguard.
234     */
235    @Deprecated
236    public KeyguardLock newKeyguardLock(String tag) {
237        return new KeyguardLock(tag);
238    }
239
240    /**
241     * Return whether the keyguard is currently locked.
242     *
243     * @return true if keyguard is locked.
244     */
245    public boolean isKeyguardLocked() {
246        try {
247            return mWM.isKeyguardLocked();
248        } catch (RemoteException ex) {
249            return false;
250        }
251    }
252
253    /**
254     * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card
255     * is currently locked.
256     *
257     * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states.
258     *
259     * @return true if a PIN, pattern or password is set or a SIM card is locked.
260     */
261    public boolean isKeyguardSecure() {
262        try {
263            return mWM.isKeyguardSecure();
264        } catch (RemoteException ex) {
265            return false;
266        }
267    }
268
269    /**
270     * If keyguard screen is showing or in restricted key input mode (i.e. in
271     * keyguard password emergency screen). When in such mode, certain keys,
272     * such as the Home key and the right soft keys, don't work.
273     *
274     * @return true if in keyguard restricted input mode.
275     *
276     * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode
277     */
278    public boolean inKeyguardRestrictedInputMode() {
279        try {
280            return mWM.inKeyguardRestrictedInputMode();
281        } catch (RemoteException ex) {
282            return false;
283        }
284    }
285
286    /**
287     * Returns whether the device is currently locked and requires a PIN, pattern or
288     * password to unlock.
289     *
290     * @return true if unlocking the device currently requires a PIN, pattern or
291     * password.
292     */
293    public boolean isDeviceLocked() {
294        return isDeviceLocked(UserHandle.getCallingUserId());
295    }
296
297    /**
298     * Per-user version of {@link #isDeviceLocked()}.
299     *
300     * @hide
301     */
302    public boolean isDeviceLocked(int userId) {
303        ITrustManager trustManager = getTrustManager();
304        try {
305            return trustManager.isDeviceLocked(userId);
306        } catch (RemoteException e) {
307            return false;
308        }
309    }
310
311    /**
312     * Returns whether the device is secured with a PIN, pattern or
313     * password.
314     *
315     * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure.
316     *
317     * @return true if a PIN, pattern or password was set.
318     */
319    public boolean isDeviceSecure() {
320        return isDeviceSecure(UserHandle.getCallingUserId());
321    }
322
323    /**
324     * Per-user version of {@link #isDeviceSecure()}.
325     *
326     * @hide
327     */
328    public boolean isDeviceSecure(int userId) {
329        ITrustManager trustManager = getTrustManager();
330        try {
331            return trustManager.isDeviceSecure(userId);
332        } catch (RemoteException e) {
333            return false;
334        }
335    }
336
337    private synchronized ITrustManager getTrustManager() {
338        if (mTrustManager == null) {
339            mTrustManager = ITrustManager.Stub.asInterface(
340                    ServiceManager.getService(Context.TRUST_SERVICE));
341        }
342        return mTrustManager;
343    }
344
345    /**
346     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
347     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
348     * instead; this allows you to seamlessly hide the keyguard as your application
349     * moves in and out of the foreground and does not require that any special
350     * permissions be requested.
351     *
352     * Exit the keyguard securely.  The use case for this api is that, after
353     * disabling the keyguard, your app, which was granted permission to
354     * disable the keyguard and show a limited amount of information deemed
355     * safe without the user getting past the keyguard, needs to navigate to
356     * something that is not safe to view without getting past the keyguard.
357     *
358     * This will, if the keyguard is secure, bring up the unlock screen of
359     * the keyguard.
360     *
361     * <p>This method requires the caller to hold the permission
362     * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
363     *
364     * @param callback Let's you know whether the operation was succesful and
365     *   it is safe to launch anything that would normally be considered safe
366     *   once the user has gotten past the keyguard.
367     */
368    @Deprecated
369    @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
370    public void exitKeyguardSecurely(final OnKeyguardExitResult callback) {
371        try {
372            mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() {
373                public void onKeyguardExitResult(boolean success) throws RemoteException {
374                    if (callback != null) {
375                        callback.onKeyguardExitResult(success);
376                    }
377                }
378            });
379        } catch (RemoteException e) {
380
381        }
382    }
383}
384