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 17 package android.app; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemService; 24 import android.app.trust.ITrustManager; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.os.Binder; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.Looper; 33 import android.os.RemoteException; 34 import android.os.ServiceManager; 35 import android.os.ServiceManager.ServiceNotFoundException; 36 import android.os.UserHandle; 37 import android.util.Log; 38 import android.view.IOnKeyguardExitResult; 39 import android.view.IWindowManager; 40 import android.view.WindowManager.LayoutParams; 41 import android.view.WindowManagerGlobal; 42 43 import com.android.internal.policy.IKeyguardDismissCallback; 44 45 import java.util.List; 46 47 /** 48 * Class that can be used to lock and unlock the keyboard. The 49 * actual class to control the keyboard locking is 50 * {@link android.app.KeyguardManager.KeyguardLock}. 51 */ 52 @SystemService(Context.KEYGUARD_SERVICE) 53 public class KeyguardManager { 54 55 private static final String TAG = "KeyguardManager"; 56 57 private final Context mContext; 58 private final IWindowManager mWM; 59 private final IActivityManager mAm; 60 private final ITrustManager mTrustManager; 61 62 /** 63 * Intent used to prompt user for device credentials. 64 * @hide 65 */ 66 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL = 67 "android.app.action.CONFIRM_DEVICE_CREDENTIAL"; 68 69 /** 70 * Intent used to prompt user for device credentials. 71 * @hide 72 */ 73 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER = 74 "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER"; 75 76 /** 77 * A CharSequence dialog title to show to the user when used with a 78 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 79 * @hide 80 */ 81 public static final String EXTRA_TITLE = "android.app.extra.TITLE"; 82 83 /** 84 * A CharSequence description to show to the user when used with 85 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 86 * @hide 87 */ 88 public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION"; 89 90 /** 91 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 92 * for the current user of the device. The caller is expected to launch this activity using 93 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 94 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 95 * 96 * @return the intent for launching the activity or null if no password is required. 97 **/ createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description)98 public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) { 99 if (!isDeviceSecure()) return null; 100 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL); 101 intent.putExtra(EXTRA_TITLE, title); 102 intent.putExtra(EXTRA_DESCRIPTION, description); 103 104 // explicitly set the package for security 105 intent.setPackage(getSettingsPackageForIntent(intent)); 106 return intent; 107 } 108 109 /** 110 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 111 * for the given user. The caller is expected to launch this activity using 112 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 113 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 114 * 115 * @return the intent for launching the activity or null if no password is required. 116 * 117 * @hide 118 */ createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId)119 public Intent createConfirmDeviceCredentialIntent( 120 CharSequence title, CharSequence description, int userId) { 121 if (!isDeviceSecure(userId)) return null; 122 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER); 123 intent.putExtra(EXTRA_TITLE, title); 124 intent.putExtra(EXTRA_DESCRIPTION, description); 125 intent.putExtra(Intent.EXTRA_USER_ID, userId); 126 127 // explicitly set the package for security 128 intent.setPackage(getSettingsPackageForIntent(intent)); 129 130 return intent; 131 } 132 getSettingsPackageForIntent(Intent intent)133 private String getSettingsPackageForIntent(Intent intent) { 134 List<ResolveInfo> resolveInfos = mContext.getPackageManager() 135 .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); 136 for (int i = 0; i < resolveInfos.size(); i++) { 137 return resolveInfos.get(i).activityInfo.packageName; 138 } 139 140 return "com.android.settings"; 141 } 142 143 /** 144 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 145 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 146 * instead; this allows you to seamlessly hide the keyguard as your application 147 * moves in and out of the foreground and does not require that any special 148 * permissions be requested. 149 * 150 * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows 151 * you to disable / reenable the keyguard. 152 */ 153 @Deprecated 154 public class KeyguardLock { 155 private final IBinder mToken = new Binder(); 156 private final String mTag; 157 KeyguardLock(String tag)158 KeyguardLock(String tag) { 159 mTag = tag; 160 } 161 162 /** 163 * Disable the keyguard from showing. If the keyguard is currently 164 * showing, hide it. The keyguard will be prevented from showing again 165 * until {@link #reenableKeyguard()} is called. 166 * 167 * A good place to call this is from {@link android.app.Activity#onResume()} 168 * 169 * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} 170 * is enabled that requires a password. 171 * 172 * @see #reenableKeyguard() 173 */ 174 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) disableKeyguard()175 public void disableKeyguard() { 176 try { 177 mWM.disableKeyguard(mToken, mTag); 178 } catch (RemoteException ex) { 179 } 180 } 181 182 /** 183 * Reenable the keyguard. The keyguard will reappear if the previous 184 * call to {@link #disableKeyguard()} caused it to be hidden. 185 * 186 * A good place to call this is from {@link android.app.Activity#onPause()} 187 * 188 * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} 189 * is enabled that requires a password. 190 * 191 * @see #disableKeyguard() 192 */ 193 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) reenableKeyguard()194 public void reenableKeyguard() { 195 try { 196 mWM.reenableKeyguard(mToken); 197 } catch (RemoteException ex) { 198 } 199 } 200 } 201 202 /** 203 * @deprecated Use {@link KeyguardDismissCallback} 204 * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify 205 * caller of result. 206 */ 207 @Deprecated 208 public interface OnKeyguardExitResult { 209 210 /** 211 * @param success True if the user was able to authenticate, false if 212 * not. 213 */ onKeyguardExitResult(boolean success)214 void onKeyguardExitResult(boolean success); 215 } 216 217 /** 218 * Callback passed to {@link KeyguardManager#dismissKeyguard} to notify caller of result. 219 */ 220 public static abstract class KeyguardDismissCallback { 221 222 /** 223 * Called when dismissing Keyguard is currently not feasible, i.e. when Keyguard is not 224 * available, not showing or when the activity requesting the Keyguard dismissal isn't 225 * showing or isn't showing behind Keyguard. 226 */ onDismissError()227 public void onDismissError() { } 228 229 /** 230 * Called when dismissing Keyguard has succeeded and the device is now unlocked. 231 */ onDismissSucceeded()232 public void onDismissSucceeded() { } 233 234 /** 235 * Called when dismissing Keyguard has been cancelled, i.e. when the user cancelled the 236 * operation or the bouncer was hidden for some other reason. 237 */ onDismissCancelled()238 public void onDismissCancelled() { } 239 } 240 KeyguardManager(Context context)241 KeyguardManager(Context context) throws ServiceNotFoundException { 242 mContext = context; 243 mWM = WindowManagerGlobal.getWindowManagerService(); 244 mAm = ActivityManager.getService(); 245 mTrustManager = ITrustManager.Stub.asInterface( 246 ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE)); 247 } 248 249 /** 250 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 251 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 252 * instead; this allows you to seamlessly hide the keyguard as your application 253 * moves in and out of the foreground and does not require that any special 254 * permissions be requested. 255 * 256 * Enables you to lock or unlock the keyboard. Get an instance of this class by 257 * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. 258 * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}. 259 * @param tag A tag that informally identifies who you are (for debugging who 260 * is disabling he keyguard). 261 * 262 * @return A {@link KeyguardLock} handle to use to disable and reenable the 263 * keyguard. 264 */ 265 @Deprecated newKeyguardLock(String tag)266 public KeyguardLock newKeyguardLock(String tag) { 267 return new KeyguardLock(tag); 268 } 269 270 /** 271 * Return whether the keyguard is currently locked. 272 * 273 * @return true if keyguard is locked. 274 */ isKeyguardLocked()275 public boolean isKeyguardLocked() { 276 try { 277 return mWM.isKeyguardLocked(); 278 } catch (RemoteException ex) { 279 return false; 280 } 281 } 282 283 /** 284 * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card 285 * is currently locked. 286 * 287 * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states. 288 * 289 * @return true if a PIN, pattern or password is set or a SIM card is locked. 290 */ isKeyguardSecure()291 public boolean isKeyguardSecure() { 292 try { 293 return mWM.isKeyguardSecure(); 294 } catch (RemoteException ex) { 295 return false; 296 } 297 } 298 299 /** 300 * If keyguard screen is showing or in restricted key input mode (i.e. in 301 * keyguard password emergency screen). When in such mode, certain keys, 302 * such as the Home key and the right soft keys, don't work. 303 * 304 * @return true if in keyguard restricted input mode. 305 * 306 * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode 307 */ inKeyguardRestrictedInputMode()308 public boolean inKeyguardRestrictedInputMode() { 309 try { 310 return mWM.inKeyguardRestrictedInputMode(); 311 } catch (RemoteException ex) { 312 return false; 313 } 314 } 315 316 /** 317 * Returns whether the device is currently locked and requires a PIN, pattern or 318 * password to unlock. 319 * 320 * @return true if unlocking the device currently requires a PIN, pattern or 321 * password. 322 */ isDeviceLocked()323 public boolean isDeviceLocked() { 324 return isDeviceLocked(UserHandle.myUserId()); 325 } 326 327 /** 328 * Per-user version of {@link #isDeviceLocked()}. 329 * 330 * @hide 331 */ isDeviceLocked(int userId)332 public boolean isDeviceLocked(int userId) { 333 try { 334 return mTrustManager.isDeviceLocked(userId); 335 } catch (RemoteException e) { 336 return false; 337 } 338 } 339 340 /** 341 * Returns whether the device is secured with a PIN, pattern or 342 * password. 343 * 344 * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure. 345 * 346 * @return true if a PIN, pattern or password was set. 347 */ isDeviceSecure()348 public boolean isDeviceSecure() { 349 return isDeviceSecure(UserHandle.myUserId()); 350 } 351 352 /** 353 * Per-user version of {@link #isDeviceSecure()}. 354 * 355 * @hide 356 */ isDeviceSecure(int userId)357 public boolean isDeviceSecure(int userId) { 358 try { 359 return mTrustManager.isDeviceSecure(userId); 360 } catch (RemoteException e) { 361 return false; 362 } 363 } 364 365 /** @removed */ 366 @Deprecated dismissKeyguard(@onNull Activity activity, @Nullable KeyguardDismissCallback callback, @Nullable Handler handler)367 public void dismissKeyguard(@NonNull Activity activity, 368 @Nullable KeyguardDismissCallback callback, @Nullable Handler handler) { 369 requestDismissKeyguard(activity, callback); 370 } 371 372 /** 373 * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to 374 * be dismissed. 375 * <p> 376 * If the Keyguard is not secure or the device is currently in a trusted state, calling this 377 * method will immediately dismiss the Keyguard without any user interaction. 378 * <p> 379 * If the Keyguard is secure and the device is not in a trusted state, this will bring up the 380 * UI so the user can enter their credentials. 381 * 382 * @param activity The activity requesting the dismissal. The activity must be either visible 383 * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in 384 * which it would be visible if Keyguard would not be hiding it. If that's not 385 * the case, the request will fail immediately and 386 * {@link KeyguardDismissCallback#onDismissError} will be invoked. 387 * @param callback The callback to be called if the request to dismiss Keyguard was successful 388 * or {@code null} if the caller isn't interested in knowing the result. The 389 * callback will not be invoked if the activity was destroyed before the 390 * callback was received. 391 */ requestDismissKeyguard(@onNull Activity activity, @Nullable KeyguardDismissCallback callback)392 public void requestDismissKeyguard(@NonNull Activity activity, 393 @Nullable KeyguardDismissCallback callback) { 394 try { 395 mAm.dismissKeyguard(activity.getActivityToken(), new IKeyguardDismissCallback.Stub() { 396 @Override 397 public void onDismissError() throws RemoteException { 398 if (callback != null && !activity.isDestroyed()) { 399 activity.mHandler.post(callback::onDismissError); 400 } 401 } 402 403 @Override 404 public void onDismissSucceeded() throws RemoteException { 405 if (callback != null && !activity.isDestroyed()) { 406 activity.mHandler.post(callback::onDismissSucceeded); 407 } 408 } 409 410 @Override 411 public void onDismissCancelled() throws RemoteException { 412 if (callback != null && !activity.isDestroyed()) { 413 activity.mHandler.post(callback::onDismissCancelled); 414 } 415 } 416 }); 417 } catch (RemoteException e) { 418 Log.i(TAG, "Failed to dismiss keyguard: " + e); 419 } 420 } 421 422 /** 423 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 424 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 425 * instead; this allows you to seamlessly hide the keyguard as your application 426 * moves in and out of the foreground and does not require that any special 427 * permissions be requested. 428 * 429 * Exit the keyguard securely. The use case for this api is that, after 430 * disabling the keyguard, your app, which was granted permission to 431 * disable the keyguard and show a limited amount of information deemed 432 * safe without the user getting past the keyguard, needs to navigate to 433 * something that is not safe to view without getting past the keyguard. 434 * 435 * This will, if the keyguard is secure, bring up the unlock screen of 436 * the keyguard. 437 * 438 * @param callback Let's you know whether the operation was succesful and 439 * it is safe to launch anything that would normally be considered safe 440 * once the user has gotten past the keyguard. 441 */ 442 @Deprecated 443 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) exitKeyguardSecurely(final OnKeyguardExitResult callback)444 public void exitKeyguardSecurely(final OnKeyguardExitResult callback) { 445 try { 446 mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() { 447 public void onKeyguardExitResult(boolean success) throws RemoteException { 448 if (callback != null) { 449 callback.onKeyguardExitResult(success); 450 } 451 } 452 }); 453 } catch (RemoteException e) { 454 455 } 456 } 457 } 458