KeyguardManager.java revision 40cd8e410db8e9d78e5aef222c498a7c2dbf2dd4
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.UserInfo;
26import android.os.Binder;
27import android.os.RemoteException;
28import android.os.IBinder;
29import android.os.IUserManager;
30import android.os.ServiceManager;
31import android.os.ServiceManager.ServiceNotFoundException;
32import android.os.UserHandle;
33import android.os.UserManager;
34import android.view.IWindowManager;
35import android.view.IOnKeyguardExitResult;
36import android.view.WindowManagerGlobal;
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        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
93            intent.setPackage("com.google.android.apps.wearable.settings");
94        } else {
95            // For security reasons, only allow this to come from system settings.
96            intent.setPackage("com.android.settings");
97        }
98        return intent;
99    }
100
101    /**
102     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
103     * for the given user. The caller is expected to launch this activity using
104     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
105     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
106     *
107     * @return the intent for launching the activity or null if no password is required.
108     *
109     * @hide
110     */
111    public Intent createConfirmDeviceCredentialIntent(
112            CharSequence title, CharSequence description, int userId) {
113        if (!isDeviceSecure(userId)) return null;
114        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
115        intent.putExtra(EXTRA_TITLE, title);
116        intent.putExtra(EXTRA_DESCRIPTION, description);
117        intent.putExtra(Intent.EXTRA_USER_ID, userId);
118        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
119            intent.setPackage("com.google.android.apps.wearable.settings");
120        } else {
121            // For security reasons, only allow this to come from system settings.
122            intent.setPackage("com.android.settings");
123        }
124        return intent;
125    }
126
127    /**
128     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
129     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
130     * instead; this allows you to seamlessly hide the keyguard as your application
131     * moves in and out of the foreground and does not require that any special
132     * permissions be requested.
133     *
134     * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows
135     * you to disable / reenable the keyguard.
136     */
137    @Deprecated
138    public class KeyguardLock {
139        private final IBinder mToken = new Binder();
140        private final String mTag;
141
142        KeyguardLock(String tag) {
143            mTag = tag;
144        }
145
146        /**
147         * Disable the keyguard from showing.  If the keyguard is currently
148         * showing, hide it.  The keyguard will be prevented from showing again
149         * until {@link #reenableKeyguard()} is called.
150         *
151         * A good place to call this is from {@link android.app.Activity#onResume()}
152         *
153         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager}
154         * is enabled that requires a password.
155         *
156         * <p>This method requires the caller to hold the permission
157         * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
158         *
159         * @see #reenableKeyguard()
160         */
161        @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
162        public void disableKeyguard() {
163            try {
164                mWM.disableKeyguard(mToken, mTag);
165            } catch (RemoteException ex) {
166            }
167        }
168
169        /**
170         * Reenable the keyguard.  The keyguard will reappear if the previous
171         * call to {@link #disableKeyguard()} caused it to be hidden.
172         *
173         * A good place to call this is from {@link android.app.Activity#onPause()}
174         *
175         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager}
176         * is enabled that requires a password.
177         *
178         * <p>This method requires the caller to hold the permission
179         * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
180         *
181         * @see #disableKeyguard()
182         */
183        @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
184        public void reenableKeyguard() {
185            try {
186                mWM.reenableKeyguard(mToken);
187            } catch (RemoteException ex) {
188            }
189        }
190    }
191
192    /**
193     * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify
194     * caller of result.
195     */
196    public interface OnKeyguardExitResult {
197
198        /**
199         * @param success True if the user was able to authenticate, false if
200         *   not.
201         */
202        void onKeyguardExitResult(boolean success);
203    }
204
205
206    KeyguardManager(Context context) throws ServiceNotFoundException {
207        mContext = context;
208        mWM = WindowManagerGlobal.getWindowManagerService();
209        mTrustManager = ITrustManager.Stub.asInterface(
210                ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE));
211        mUserManager = IUserManager.Stub.asInterface(
212                ServiceManager.getServiceOrThrow(Context.USER_SERVICE));
213    }
214
215    /**
216     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
217     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
218     * instead; this allows you to seamlessly hide the keyguard as your application
219     * moves in and out of the foreground and does not require that any special
220     * permissions be requested.
221     *
222     * Enables you to lock or unlock the keyboard. Get an instance of this class by
223     * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
224     * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}.
225     * @param tag A tag that informally identifies who you are (for debugging who
226     *   is disabling he keyguard).
227     *
228     * @return A {@link KeyguardLock} handle to use to disable and reenable the
229     *   keyguard.
230     */
231    @Deprecated
232    public KeyguardLock newKeyguardLock(String tag) {
233        return new KeyguardLock(tag);
234    }
235
236    /**
237     * Return whether the keyguard is currently locked.
238     *
239     * @return true if keyguard is locked.
240     */
241    public boolean isKeyguardLocked() {
242        try {
243            return mWM.isKeyguardLocked();
244        } catch (RemoteException ex) {
245            return false;
246        }
247    }
248
249    /**
250     * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card
251     * is currently locked.
252     *
253     * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states.
254     *
255     * @return true if a PIN, pattern or password is set or a SIM card is locked.
256     */
257    public boolean isKeyguardSecure() {
258        try {
259            return mWM.isKeyguardSecure();
260        } catch (RemoteException ex) {
261            return false;
262        }
263    }
264
265    /**
266     * If keyguard screen is showing or in restricted key input mode (i.e. in
267     * keyguard password emergency screen). When in such mode, certain keys,
268     * such as the Home key and the right soft keys, don't work.
269     *
270     * @return true if in keyguard restricted input mode.
271     *
272     * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode
273     */
274    public boolean inKeyguardRestrictedInputMode() {
275        try {
276            return mWM.inKeyguardRestrictedInputMode();
277        } catch (RemoteException ex) {
278            return false;
279        }
280    }
281
282    /**
283     * Returns whether the device is currently locked and requires a PIN, pattern or
284     * password to unlock.
285     *
286     * @return true if unlocking the device currently requires a PIN, pattern or
287     * password.
288     */
289    public boolean isDeviceLocked() {
290        return isDeviceLocked(UserHandle.getCallingUserId());
291    }
292
293    /**
294     * Per-user version of {@link #isDeviceLocked()}.
295     *
296     * @hide
297     */
298    public boolean isDeviceLocked(int userId) {
299        ITrustManager trustManager = getTrustManager();
300        try {
301            return trustManager.isDeviceLocked(userId);
302        } catch (RemoteException e) {
303            return false;
304        }
305    }
306
307    /**
308     * Returns whether the device is secured with a PIN, pattern or
309     * password.
310     *
311     * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure.
312     *
313     * @return true if a PIN, pattern or password was set.
314     */
315    public boolean isDeviceSecure() {
316        return isDeviceSecure(UserHandle.getCallingUserId());
317    }
318
319    /**
320     * Per-user version of {@link #isDeviceSecure()}.
321     *
322     * @hide
323     */
324    public boolean isDeviceSecure(int userId) {
325        ITrustManager trustManager = getTrustManager();
326        try {
327            return trustManager.isDeviceSecure(userId);
328        } catch (RemoteException e) {
329            return false;
330        }
331    }
332
333    private synchronized ITrustManager getTrustManager() {
334        if (mTrustManager == null) {
335            mTrustManager = ITrustManager.Stub.asInterface(
336                    ServiceManager.getService(Context.TRUST_SERVICE));
337        }
338        return mTrustManager;
339    }
340
341    /**
342     * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
343     * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
344     * instead; this allows you to seamlessly hide the keyguard as your application
345     * moves in and out of the foreground and does not require that any special
346     * permissions be requested.
347     *
348     * Exit the keyguard securely.  The use case for this api is that, after
349     * disabling the keyguard, your app, which was granted permission to
350     * disable the keyguard and show a limited amount of information deemed
351     * safe without the user getting past the keyguard, needs to navigate to
352     * something that is not safe to view without getting past the keyguard.
353     *
354     * This will, if the keyguard is secure, bring up the unlock screen of
355     * the keyguard.
356     *
357     * <p>This method requires the caller to hold the permission
358     * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
359     *
360     * @param callback Let's you know whether the operation was succesful and
361     *   it is safe to launch anything that would normally be considered safe
362     *   once the user has gotten past the keyguard.
363     */
364    @Deprecated
365    @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
366    public void exitKeyguardSecurely(final OnKeyguardExitResult callback) {
367        try {
368            mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() {
369                public void onKeyguardExitResult(boolean success) throws RemoteException {
370                    if (callback != null) {
371                        callback.onKeyguardExitResult(success);
372                    }
373                }
374            });
375        } catch (RemoteException e) {
376
377        }
378    }
379}
380