LockPatternUtils.java revision 6ee7d25010d4f23b44a151f3953225ba253de8af
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 com.android.internal.widget; 18 19import android.Manifest; 20import android.app.ActivityManagerNative; 21import android.app.admin.DevicePolicyManager; 22import android.appwidget.AppWidgetManager; 23import android.content.ContentResolver; 24import android.content.Context; 25import android.content.Intent; 26import android.content.pm.PackageManager; 27import android.os.IBinder; 28import android.os.RemoteException; 29import android.os.ServiceManager; 30import android.os.SystemClock; 31import android.os.UserHandle; 32import android.os.storage.IMountService; 33import android.os.storage.StorageManager; 34import android.provider.Settings; 35import android.telephony.TelephonyManager; 36import android.text.TextUtils; 37import android.util.Log; 38import android.view.IWindowManager; 39import android.view.View; 40import android.widget.Button; 41 42import com.android.internal.R; 43import com.android.internal.telephony.ITelephony; 44import com.google.android.collect.Lists; 45 46import java.security.MessageDigest; 47import java.security.NoSuchAlgorithmException; 48import java.security.SecureRandom; 49import java.util.List; 50 51/** 52 * Utilities for the lock pattern and its settings. 53 */ 54public class LockPatternUtils { 55 56 private static final String TAG = "LockPatternUtils"; 57 58 /** 59 * The maximum number of incorrect attempts before the user is prevented 60 * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}. 61 */ 62 public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5; 63 64 /** 65 * The number of incorrect attempts before which we fall back on an alternative 66 * method of verifying the user, and resetting their lock pattern. 67 */ 68 public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20; 69 70 /** 71 * How long the user is prevented from trying again after entering the 72 * wrong pattern too many times. 73 */ 74 public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L; 75 76 /** 77 * The interval of the countdown for showing progress of the lockout. 78 */ 79 public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; 80 81 82 /** 83 * This dictates when we start telling the user that continued failed attempts will wipe 84 * their device. 85 */ 86 public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5; 87 88 /** 89 * The minimum number of dots in a valid pattern. 90 */ 91 public static final int MIN_LOCK_PATTERN_SIZE = 4; 92 93 /** 94 * The minimum number of dots the user must include in a wrong pattern 95 * attempt for it to be counted against the counts that affect 96 * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET} 97 */ 98 public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; 99 100 /** 101 * Tells the keyguard to show the user switcher when the keyguard is created. 102 */ 103 public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher"; 104 105 /** 106 * Tells the keyguard to show the security challenge when the keyguard is created. 107 */ 108 public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge"; 109 110 /** 111 * Tells the keyguard to show the widget with the specified id when the keyguard is created. 112 */ 113 public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget"; 114 115 /** 116 * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should 117 * be used 118 */ 119 public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1; 120 121 /** 122 * Pseudo-appwidget id we use to represent the default clock status widget 123 */ 124 public static final int ID_DEFAULT_STATUS_WIDGET = -2; 125 126 public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; 127 public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; 128 public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; 129 public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; 130 public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate"; 131 public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt"; 132 public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled"; 133 public final static String LOCKSCREEN_OPTIONS = "lockscreen.options"; 134 public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK 135 = "lockscreen.biometric_weak_fallback"; 136 public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY 137 = "lockscreen.biometricweakeverchosen"; 138 public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS 139 = "lockscreen.power_button_instantly_locks"; 140 public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled"; 141 142 public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory"; 143 144 private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO; 145 private static final String LOCK_SCREEN_OWNER_INFO_ENABLED = 146 Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 147 148 private final Context mContext; 149 private final ContentResolver mContentResolver; 150 private DevicePolicyManager mDevicePolicyManager; 151 private ILockSettings mLockSettingsService; 152 153 private final boolean mMultiUserMode; 154 155 // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils. 156 private static volatile int sCurrentUserId = UserHandle.USER_NULL; 157 158 public DevicePolicyManager getDevicePolicyManager() { 159 if (mDevicePolicyManager == null) { 160 mDevicePolicyManager = 161 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 162 if (mDevicePolicyManager == null) { 163 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?", 164 new IllegalStateException("Stack trace:")); 165 } 166 } 167 return mDevicePolicyManager; 168 } 169 170 /** 171 * @param contentResolver Used to look up and save settings. 172 */ 173 public LockPatternUtils(Context context) { 174 mContext = context; 175 mContentResolver = context.getContentResolver(); 176 177 // If this is being called by the system or by an application like keyguard that 178 // has permision INTERACT_ACROSS_USERS, then LockPatternUtils will operate in multi-user 179 // mode where calls are for the current user rather than the user of the calling process. 180 mMultiUserMode = context.checkCallingOrSelfPermission( 181 Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED; 182 } 183 184 private ILockSettings getLockSettings() { 185 if (mLockSettingsService == null) { 186 mLockSettingsService = ILockSettings.Stub.asInterface( 187 (IBinder) ServiceManager.getService("lock_settings")); 188 } 189 return mLockSettingsService; 190 } 191 192 public int getRequestedMinimumPasswordLength() { 193 return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId()); 194 } 195 196 /** 197 * Gets the device policy password mode. If the mode is non-specific, returns 198 * MODE_PATTERN which allows the user to choose anything. 199 */ 200 public int getRequestedPasswordQuality() { 201 return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId()); 202 } 203 204 public int getRequestedPasswordHistoryLength() { 205 return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId()); 206 } 207 208 public int getRequestedPasswordMinimumLetters() { 209 return getDevicePolicyManager().getPasswordMinimumLetters(null, 210 getCurrentOrCallingUserId()); 211 } 212 213 public int getRequestedPasswordMinimumUpperCase() { 214 return getDevicePolicyManager().getPasswordMinimumUpperCase(null, 215 getCurrentOrCallingUserId()); 216 } 217 218 public int getRequestedPasswordMinimumLowerCase() { 219 return getDevicePolicyManager().getPasswordMinimumLowerCase(null, 220 getCurrentOrCallingUserId()); 221 } 222 223 public int getRequestedPasswordMinimumNumeric() { 224 return getDevicePolicyManager().getPasswordMinimumNumeric(null, 225 getCurrentOrCallingUserId()); 226 } 227 228 public int getRequestedPasswordMinimumSymbols() { 229 return getDevicePolicyManager().getPasswordMinimumSymbols(null, 230 getCurrentOrCallingUserId()); 231 } 232 233 public int getRequestedPasswordMinimumNonLetter() { 234 return getDevicePolicyManager().getPasswordMinimumNonLetter(null, 235 getCurrentOrCallingUserId()); 236 } 237 238 /** 239 * Returns the actual password mode, as set by keyguard after updating the password. 240 * 241 * @return 242 */ 243 public void reportFailedPasswordAttempt() { 244 getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId()); 245 } 246 247 public void reportSuccessfulPasswordAttempt() { 248 getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId()); 249 } 250 251 public void setCurrentUser(int userId) { 252 sCurrentUserId = userId; 253 } 254 255 public int getCurrentUser() { 256 if (sCurrentUserId != UserHandle.USER_NULL) { 257 // Someone is regularly updating using setCurrentUser() use that value. 258 return sCurrentUserId; 259 } 260 try { 261 return ActivityManagerNative.getDefault().getCurrentUser().id; 262 } catch (RemoteException re) { 263 return UserHandle.USER_OWNER; 264 } 265 } 266 267 public void removeUser(int userId) { 268 try { 269 getLockSettings().removeUser(userId); 270 } catch (RemoteException re) { 271 Log.e(TAG, "Couldn't remove lock settings for user " + userId); 272 } 273 } 274 275 private int getCurrentOrCallingUserId() { 276 if (mMultiUserMode) { 277 // TODO: This is a little inefficient. See if all users of this are able to 278 // handle USER_CURRENT and pass that instead. 279 return getCurrentUser(); 280 } else { 281 return UserHandle.getCallingUserId(); 282 } 283 } 284 285 /** 286 * Check to see if a pattern matches the saved pattern. If no pattern exists, 287 * always returns true. 288 * @param pattern The pattern to check. 289 * @return Whether the pattern matches the stored one. 290 */ 291 public boolean checkPattern(List<LockPatternView.Cell> pattern) { 292 final int userId = getCurrentOrCallingUserId(); 293 try { 294 return getLockSettings().checkPattern(patternToString(pattern), userId); 295 } catch (RemoteException re) { 296 return true; 297 } 298 } 299 300 /** 301 * Check to see if a password matches the saved password. If no password exists, 302 * always returns true. 303 * @param password The password to check. 304 * @return Whether the password matches the stored one. 305 */ 306 public boolean checkPassword(String password) { 307 final int userId = getCurrentOrCallingUserId(); 308 try { 309 return getLockSettings().checkPassword(password, userId); 310 } catch (RemoteException re) { 311 return true; 312 } 313 } 314 315 /** 316 * Check to see if a password matches any of the passwords stored in the 317 * password history. 318 * 319 * @param password The password to check. 320 * @return Whether the password matches any in the history. 321 */ 322 public boolean checkPasswordHistory(String password) { 323 String passwordHashString = new String(passwordToHash(password)); 324 String passwordHistory = getString(PASSWORD_HISTORY_KEY); 325 if (passwordHistory == null) { 326 return false; 327 } 328 // Password History may be too long... 329 int passwordHashLength = passwordHashString.length(); 330 int passwordHistoryLength = getRequestedPasswordHistoryLength(); 331 if(passwordHistoryLength == 0) { 332 return false; 333 } 334 int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength 335 + passwordHistoryLength - 1; 336 if (passwordHistory.length() > neededPasswordHistoryLength) { 337 passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength); 338 } 339 return passwordHistory.contains(passwordHashString); 340 } 341 342 /** 343 * Check to see if the user has stored a lock pattern. 344 * @return Whether a saved pattern exists. 345 */ 346 public boolean savedPatternExists() { 347 try { 348 return getLockSettings().havePattern(getCurrentOrCallingUserId()); 349 } catch (RemoteException re) { 350 return false; 351 } 352 } 353 354 /** 355 * Check to see if the user has stored a lock pattern. 356 * @return Whether a saved pattern exists. 357 */ 358 public boolean savedPasswordExists() { 359 try { 360 return getLockSettings().havePassword(getCurrentOrCallingUserId()); 361 } catch (RemoteException re) { 362 return false; 363 } 364 } 365 366 /** 367 * Return true if the user has ever chosen a pattern. This is true even if the pattern is 368 * currently cleared. 369 * 370 * @return True if the user has ever chosen a pattern. 371 */ 372 public boolean isPatternEverChosen() { 373 return getBoolean(PATTERN_EVER_CHOSEN_KEY, false); 374 } 375 376 /** 377 * Return true if the user has ever chosen biometric weak. This is true even if biometric 378 * weak is not current set. 379 * 380 * @return True if the user has ever chosen biometric weak. 381 */ 382 public boolean isBiometricWeakEverChosen() { 383 return getBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, false); 384 } 385 386 /** 387 * Used by device policy manager to validate the current password 388 * information it has. 389 */ 390 public int getActivePasswordQuality() { 391 int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 392 // Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to 393 // return biometric_weak if that is being used instead of the backup 394 int quality = 395 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 396 switch (quality) { 397 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 398 if (isLockPatternEnabled()) { 399 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 400 } 401 break; 402 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK: 403 if (isBiometricWeakInstalled()) { 404 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; 405 } 406 break; 407 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 408 if (isLockPasswordEnabled()) { 409 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 410 } 411 break; 412 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 413 if (isLockPasswordEnabled()) { 414 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 415 } 416 break; 417 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 418 if (isLockPasswordEnabled()) { 419 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 420 } 421 break; 422 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 423 if (isLockPasswordEnabled()) { 424 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 425 } 426 break; 427 } 428 429 return activePasswordQuality; 430 } 431 432 /** 433 * Clear any lock pattern or password. 434 */ 435 public void clearLock(boolean isFallback) { 436 if(!isFallback) deleteGallery(); 437 saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 438 setLockPatternEnabled(false); 439 saveLockPattern(null); 440 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); 441 setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); 442 } 443 444 /** 445 * Disable showing lock screen at all when the DevicePolicyManager allows it. 446 * This is only meaningful if pattern, pin or password are not set. 447 * 448 * @param disable Disables lock screen when true 449 */ 450 public void setLockScreenDisabled(boolean disable) { 451 setLong(DISABLE_LOCKSCREEN_KEY, disable ? 1 : 0); 452 } 453 454 /** 455 * Determine if LockScreen can be disabled. This is used, for example, to tell if we should 456 * show LockScreen or go straight to the home screen. 457 * 458 * @return true if lock screen is can be disabled 459 */ 460 public boolean isLockScreenDisabled() { 461 return !isSecure() && getLong(DISABLE_LOCKSCREEN_KEY, 0) != 0; 462 } 463 464 /** 465 * Calls back SetupFaceLock to delete the temporary gallery file 466 */ 467 public void deleteTempGallery() { 468 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY"); 469 intent.putExtra("deleteTempGallery", true); 470 mContext.sendBroadcast(intent); 471 } 472 473 /** 474 * Calls back SetupFaceLock to delete the gallery file when the lock type is changed 475 */ 476 void deleteGallery() { 477 if(usingBiometricWeak()) { 478 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY"); 479 intent.putExtra("deleteGallery", true); 480 mContext.sendBroadcast(intent); 481 } 482 } 483 484 /** 485 * Save a lock pattern. 486 * @param pattern The new pattern to save. 487 */ 488 public void saveLockPattern(List<LockPatternView.Cell> pattern) { 489 this.saveLockPattern(pattern, false); 490 } 491 492 /** 493 * Save a lock pattern. 494 * @param pattern The new pattern to save. 495 * @param isFallback Specifies if this is a fallback to biometric weak 496 */ 497 public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) { 498 try { 499 getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId()); 500 DevicePolicyManager dpm = getDevicePolicyManager(); 501 if (pattern != null) { 502 503 int userHandle = getCurrentOrCallingUserId(); 504 if (userHandle == UserHandle.USER_OWNER) { 505 String stringPattern = patternToString(pattern); 506 updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern); 507 } 508 509 setBoolean(PATTERN_EVER_CHOSEN_KEY, true); 510 if (!isFallback) { 511 deleteGallery(); 512 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 513 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 514 pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 515 } else { 516 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); 517 setLong(PASSWORD_TYPE_ALTERNATE_KEY, 518 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 519 finishBiometricWeak(); 520 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 521 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 522 } 523 } else { 524 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 525 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 526 } 527 } catch (RemoteException re) { 528 Log.e(TAG, "Couldn't save lock pattern " + re); 529 } 530 } 531 532 public void setOwnerInfo(String info, int userId) { 533 setString(LOCK_SCREEN_OWNER_INFO, info, userId); 534 } 535 536 public void setOwnerInfoEnabled(boolean enabled) { 537 setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled); 538 } 539 540 public String getOwnerInfo(int userId) { 541 return getString(LOCK_SCREEN_OWNER_INFO); 542 } 543 544 public boolean isOwnerInfoEnabled() { 545 return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false); 546 } 547 548 /** 549 * Compute the password quality from the given password string. 550 */ 551 static public int computePasswordQuality(String password) { 552 boolean hasDigit = false; 553 boolean hasNonDigit = false; 554 final int len = password.length(); 555 for (int i = 0; i < len; i++) { 556 if (Character.isDigit(password.charAt(i))) { 557 hasDigit = true; 558 } else { 559 hasNonDigit = true; 560 } 561 } 562 563 if (hasNonDigit && hasDigit) { 564 return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 565 } 566 if (hasNonDigit) { 567 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 568 } 569 if (hasDigit) { 570 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 571 } 572 return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 573 } 574 575 /** Update the encryption password if it is enabled **/ 576 private void updateEncryptionPassword(int type, String password) { 577 DevicePolicyManager dpm = getDevicePolicyManager(); 578 if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId()) 579 != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) { 580 return; 581 } 582 583 IBinder service = ServiceManager.getService("mount"); 584 if (service == null) { 585 Log.e(TAG, "Could not find the mount service to update the encryption password"); 586 return; 587 } 588 589 IMountService mountService = IMountService.Stub.asInterface(service); 590 try { 591 mountService.changeEncryptionPassword(type, password); 592 } catch (RemoteException e) { 593 Log.e(TAG, "Error changing encryption password", e); 594 } 595 } 596 597 /** 598 * Save a lock password. Does not ensure that the password is as good 599 * as the requested mode, but will adjust the mode to be as good as the 600 * pattern. 601 * @param password The password to save 602 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 603 */ 604 public void saveLockPassword(String password, int quality) { 605 this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId()); 606 } 607 608 /** 609 * Save a lock password. Does not ensure that the password is as good 610 * as the requested mode, but will adjust the mode to be as good as the 611 * pattern. 612 * @param password The password to save 613 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 614 * @param isFallback Specifies if this is a fallback to biometric weak 615 */ 616 public void saveLockPassword(String password, int quality, boolean isFallback) { 617 saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId()); 618 } 619 620 /** 621 * Save a lock password. Does not ensure that the password is as good 622 * as the requested mode, but will adjust the mode to be as good as the 623 * pattern. 624 * @param password The password to save 625 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 626 * @param isFallback Specifies if this is a fallback to biometric weak 627 * @param userHandle The userId of the user to change the password for 628 */ 629 public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { 630 try { 631 getLockSettings().setLockPassword(password, userHandle); 632 DevicePolicyManager dpm = getDevicePolicyManager(); 633 if (password != null) { 634 int computedQuality = computePasswordQuality(password); 635 636 if (userHandle == UserHandle.USER_OWNER) { 637 // Update the encryption password. 638 int type = computedQuality == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 639 ? StorageManager.CRYPT_TYPE_PIN : StorageManager.CRYPT_TYPE_PASSWORD; 640 updateEncryptionPassword(type, password); 641 } 642 643 if (!isFallback) { 644 deleteGallery(); 645 setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle); 646 if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 647 int letters = 0; 648 int uppercase = 0; 649 int lowercase = 0; 650 int numbers = 0; 651 int symbols = 0; 652 int nonletter = 0; 653 for (int i = 0; i < password.length(); i++) { 654 char c = password.charAt(i); 655 if (c >= 'A' && c <= 'Z') { 656 letters++; 657 uppercase++; 658 } else if (c >= 'a' && c <= 'z') { 659 letters++; 660 lowercase++; 661 } else if (c >= '0' && c <= '9') { 662 numbers++; 663 nonletter++; 664 } else { 665 symbols++; 666 nonletter++; 667 } 668 } 669 dpm.setActivePasswordState(Math.max(quality, computedQuality), 670 password.length(), letters, uppercase, lowercase, 671 numbers, symbols, nonletter, userHandle); 672 } else { 673 // The password is not anything. 674 dpm.setActivePasswordState( 675 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 676 0, 0, 0, 0, 0, 0, 0, userHandle); 677 } 678 } else { 679 // Case where it's a fallback for biometric weak 680 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 681 userHandle); 682 setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality), 683 userHandle); 684 finishBiometricWeak(); 685 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 686 0, 0, 0, 0, 0, 0, 0, userHandle); 687 } 688 // Add the password to the password history. We assume all 689 // password hashes have the same length for simplicity of implementation. 690 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle); 691 if (passwordHistory == null) { 692 passwordHistory = new String(); 693 } 694 int passwordHistoryLength = getRequestedPasswordHistoryLength(); 695 if (passwordHistoryLength == 0) { 696 passwordHistory = ""; 697 } else { 698 byte[] hash = passwordToHash(password); 699 passwordHistory = new String(hash) + "," + passwordHistory; 700 // Cut it to contain passwordHistoryLength hashes 701 // and passwordHistoryLength -1 commas. 702 passwordHistory = passwordHistory.substring(0, Math.min(hash.length 703 * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory 704 .length())); 705 } 706 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); 707 } else { 708 if (userHandle == UserHandle.USER_OWNER) { 709 // Update the encryption password. 710 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, password); 711 } 712 713 dpm.setActivePasswordState( 714 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, 715 userHandle); 716 } 717 } catch (RemoteException re) { 718 // Cant do much 719 Log.e(TAG, "Unable to save lock password " + re); 720 } 721 } 722 723 /** 724 * Retrieves the quality mode we're in. 725 * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 726 * 727 * @return stored password quality 728 */ 729 public int getKeyguardStoredPasswordQuality() { 730 int quality = 731 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 732 // If the user has chosen to use weak biometric sensor, then return the backup locking 733 // method and treat biometric as a special case. 734 if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { 735 quality = 736 (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY, 737 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 738 } 739 return quality; 740 } 741 742 /** 743 * @return true if the lockscreen method is set to biometric weak 744 */ 745 public boolean usingBiometricWeak() { 746 int quality = 747 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 748 return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; 749 } 750 751 /** 752 * Deserialize a pattern. 753 * @param string The pattern serialized with {@link #patternToString} 754 * @return The pattern. 755 */ 756 public static List<LockPatternView.Cell> stringToPattern(String string) { 757 List<LockPatternView.Cell> result = Lists.newArrayList(); 758 759 final byte[] bytes = string.getBytes(); 760 for (int i = 0; i < bytes.length; i++) { 761 byte b = bytes[i]; 762 result.add(LockPatternView.Cell.of(b / 3, b % 3)); 763 } 764 return result; 765 } 766 767 /** 768 * Serialize a pattern. 769 * @param pattern The pattern. 770 * @return The pattern in string form. 771 */ 772 public static String patternToString(List<LockPatternView.Cell> pattern) { 773 if (pattern == null) { 774 return ""; 775 } 776 final int patternSize = pattern.size(); 777 778 byte[] res = new byte[patternSize]; 779 for (int i = 0; i < patternSize; i++) { 780 LockPatternView.Cell cell = pattern.get(i); 781 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn()); 782 } 783 return new String(res); 784 } 785 786 /* 787 * Generate an SHA-1 hash for the pattern. Not the most secure, but it is 788 * at least a second level of protection. First level is that the file 789 * is in a location only readable by the system process. 790 * @param pattern the gesture pattern. 791 * @return the hash of the pattern in a byte array. 792 */ 793 public static byte[] patternToHash(List<LockPatternView.Cell> pattern) { 794 if (pattern == null) { 795 return null; 796 } 797 798 final int patternSize = pattern.size(); 799 byte[] res = new byte[patternSize]; 800 for (int i = 0; i < patternSize; i++) { 801 LockPatternView.Cell cell = pattern.get(i); 802 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn()); 803 } 804 try { 805 MessageDigest md = MessageDigest.getInstance("SHA-1"); 806 byte[] hash = md.digest(res); 807 return hash; 808 } catch (NoSuchAlgorithmException nsa) { 809 return res; 810 } 811 } 812 813 private String getSalt() { 814 long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0); 815 if (salt == 0) { 816 try { 817 salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 818 setLong(LOCK_PASSWORD_SALT_KEY, salt); 819 Log.v(TAG, "Initialized lock password salt"); 820 } catch (NoSuchAlgorithmException e) { 821 // Throw an exception rather than storing a password we'll never be able to recover 822 throw new IllegalStateException("Couldn't get SecureRandom number", e); 823 } 824 } 825 return Long.toHexString(salt); 826 } 827 828 /* 829 * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. 830 * Not the most secure, but it is at least a second level of protection. First level is that 831 * the file is in a location only readable by the system process. 832 * @param password the gesture pattern. 833 * @return the hash of the pattern in a byte array. 834 */ 835 public byte[] passwordToHash(String password) { 836 if (password == null) { 837 return null; 838 } 839 String algo = null; 840 byte[] hashed = null; 841 try { 842 byte[] saltedPassword = (password + getSalt()).getBytes(); 843 byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); 844 byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); 845 hashed = (toHex(sha1) + toHex(md5)).getBytes(); 846 } catch (NoSuchAlgorithmException e) { 847 Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo); 848 } 849 return hashed; 850 } 851 852 private static String toHex(byte[] ary) { 853 final String hex = "0123456789ABCDEF"; 854 String ret = ""; 855 for (int i = 0; i < ary.length; i++) { 856 ret += hex.charAt((ary[i] >> 4) & 0xf); 857 ret += hex.charAt(ary[i] & 0xf); 858 } 859 return ret; 860 } 861 862 /** 863 * @return Whether the lock password is enabled, or if it is set as a backup for biometric weak 864 */ 865 public boolean isLockPasswordEnabled() { 866 long mode = getLong(PASSWORD_TYPE_KEY, 0); 867 long backupMode = getLong(PASSWORD_TYPE_ALTERNATE_KEY, 0); 868 final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 869 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 870 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 871 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 872 final boolean backupEnabled = backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 873 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 874 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 875 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 876 877 return savedPasswordExists() && (passwordEnabled || 878 (usingBiometricWeak() && backupEnabled)); 879 } 880 881 /** 882 * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak 883 */ 884 public boolean isLockPatternEnabled() { 885 final boolean backupEnabled = 886 getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) 887 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 888 889 return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false) 890 && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) 891 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING || 892 (usingBiometricWeak() && backupEnabled)); 893 } 894 895 /** 896 * @return Whether biometric weak lock is installed and that the front facing camera exists 897 */ 898 public boolean isBiometricWeakInstalled() { 899 // Check that it's installed 900 PackageManager pm = mContext.getPackageManager(); 901 try { 902 pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES); 903 } catch (PackageManager.NameNotFoundException e) { 904 return false; 905 } 906 907 // Check that the camera is enabled 908 if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) { 909 return false; 910 } 911 if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) { 912 return false; 913 } 914 915 916 return true; 917 } 918 919 /** 920 * Set whether biometric weak liveliness is enabled. 921 */ 922 public void setBiometricWeakLivelinessEnabled(boolean enabled) { 923 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L); 924 long newFlag; 925 if (enabled) { 926 newFlag = currentFlag | FLAG_BIOMETRIC_WEAK_LIVELINESS; 927 } else { 928 newFlag = currentFlag & ~FLAG_BIOMETRIC_WEAK_LIVELINESS; 929 } 930 setLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, newFlag); 931 } 932 933 /** 934 * @return Whether the biometric weak liveliness is enabled. 935 */ 936 public boolean isBiometricWeakLivelinessEnabled() { 937 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L); 938 return ((currentFlag & FLAG_BIOMETRIC_WEAK_LIVELINESS) != 0); 939 } 940 941 /** 942 * Set whether the lock pattern is enabled. 943 */ 944 public void setLockPatternEnabled(boolean enabled) { 945 setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled); 946 } 947 948 /** 949 * @return Whether the visible pattern is enabled. 950 */ 951 public boolean isVisiblePatternEnabled() { 952 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false); 953 } 954 955 /** 956 * Set whether the visible pattern is enabled. 957 */ 958 public void setVisiblePatternEnabled(boolean enabled) { 959 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled); 960 } 961 962 /** 963 * @return Whether tactile feedback for the pattern is enabled. 964 */ 965 public boolean isTactileFeedbackEnabled() { 966 return Settings.System.getIntForUser(mContentResolver, 967 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0; 968 } 969 970 /** 971 * Set and store the lockout deadline, meaning the user can't attempt his/her unlock 972 * pattern until the deadline has passed. 973 * @return the chosen deadline. 974 */ 975 public long setLockoutAttemptDeadline() { 976 final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS; 977 setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline); 978 return deadline; 979 } 980 981 /** 982 * @return The elapsed time in millis in the future when the user is allowed to 983 * attempt to enter his/her lock pattern, or 0 if the user is welcome to 984 * enter a pattern. 985 */ 986 public long getLockoutAttemptDeadline() { 987 final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L); 988 final long now = SystemClock.elapsedRealtime(); 989 if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) { 990 return 0L; 991 } 992 return deadline; 993 } 994 995 /** 996 * @return Whether the user is permanently locked out until they verify their 997 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed 998 * attempts. 999 */ 1000 public boolean isPermanentlyLocked() { 1001 return getBoolean(LOCKOUT_PERMANENT_KEY, false); 1002 } 1003 1004 /** 1005 * Set the state of whether the device is permanently locked, meaning the user 1006 * must authenticate via other means. 1007 * 1008 * @param locked Whether the user is permanently locked out until they verify their 1009 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed 1010 * attempts. 1011 */ 1012 public void setPermanentlyLocked(boolean locked) { 1013 setBoolean(LOCKOUT_PERMANENT_KEY, locked); 1014 } 1015 1016 public boolean isEmergencyCallCapable() { 1017 return mContext.getResources().getBoolean( 1018 com.android.internal.R.bool.config_voice_capable); 1019 } 1020 1021 public boolean isPukUnlockScreenEnable() { 1022 return mContext.getResources().getBoolean( 1023 com.android.internal.R.bool.config_enable_puk_unlock_screen); 1024 } 1025 1026 public boolean isEmergencyCallEnabledWhileSimLocked() { 1027 return mContext.getResources().getBoolean( 1028 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked); 1029 } 1030 1031 /** 1032 * @return A formatted string of the next alarm (for showing on the lock screen), 1033 * or null if there is no next alarm. 1034 */ 1035 public String getNextAlarm() { 1036 String nextAlarm = Settings.System.getStringForUser(mContentResolver, 1037 Settings.System.NEXT_ALARM_FORMATTED, UserHandle.USER_CURRENT); 1038 if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) { 1039 return null; 1040 } 1041 return nextAlarm; 1042 } 1043 1044 private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) { 1045 try { 1046 return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId); 1047 } catch (RemoteException re) { 1048 return defaultValue; 1049 } 1050 } 1051 1052 private boolean getBoolean(String secureSettingKey, boolean defaultValue) { 1053 return getBoolean(secureSettingKey, defaultValue, getCurrentOrCallingUserId()); 1054 } 1055 1056 private void setBoolean(String secureSettingKey, boolean enabled, int userId) { 1057 try { 1058 getLockSettings().setBoolean(secureSettingKey, enabled, userId); 1059 } catch (RemoteException re) { 1060 // What can we do? 1061 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re); 1062 } 1063 } 1064 1065 private void setBoolean(String secureSettingKey, boolean enabled) { 1066 setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId()); 1067 } 1068 1069 public int[] getAppWidgets() { 1070 return getAppWidgets(UserHandle.USER_CURRENT); 1071 } 1072 1073 private int[] getAppWidgets(int userId) { 1074 String appWidgetIdString = Settings.Secure.getStringForUser( 1075 mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, userId); 1076 String delims = ","; 1077 if (appWidgetIdString != null && appWidgetIdString.length() > 0) { 1078 String[] appWidgetStringIds = appWidgetIdString.split(delims); 1079 int[] appWidgetIds = new int[appWidgetStringIds.length]; 1080 for (int i = 0; i < appWidgetStringIds.length; i++) { 1081 String appWidget = appWidgetStringIds[i]; 1082 try { 1083 appWidgetIds[i] = Integer.decode(appWidget); 1084 } catch (NumberFormatException e) { 1085 Log.d(TAG, "Error when parsing widget id " + appWidget); 1086 return null; 1087 } 1088 } 1089 return appWidgetIds; 1090 } 1091 return new int[0]; 1092 } 1093 1094 private static String combineStrings(int[] list, String separator) { 1095 int listLength = list.length; 1096 1097 switch (listLength) { 1098 case 0: { 1099 return ""; 1100 } 1101 case 1: { 1102 return Integer.toString(list[0]); 1103 } 1104 } 1105 1106 int strLength = 0; 1107 int separatorLength = separator.length(); 1108 1109 String[] stringList = new String[list.length]; 1110 for (int i = 0; i < listLength; i++) { 1111 stringList[i] = Integer.toString(list[i]); 1112 strLength += stringList[i].length(); 1113 if (i < listLength - 1) { 1114 strLength += separatorLength; 1115 } 1116 } 1117 1118 StringBuilder sb = new StringBuilder(strLength); 1119 1120 for (int i = 0; i < listLength; i++) { 1121 sb.append(list[i]); 1122 if (i < listLength - 1) { 1123 sb.append(separator); 1124 } 1125 } 1126 1127 return sb.toString(); 1128 } 1129 1130 // appwidget used when appwidgets are disabled (we make an exception for 1131 // default clock widget) 1132 public void writeFallbackAppWidgetId(int appWidgetId) { 1133 Settings.Secure.putIntForUser(mContentResolver, 1134 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, 1135 appWidgetId, 1136 UserHandle.USER_CURRENT); 1137 } 1138 1139 // appwidget used when appwidgets are disabled (we make an exception for 1140 // default clock widget) 1141 public int getFallbackAppWidgetId() { 1142 return Settings.Secure.getIntForUser( 1143 mContentResolver, 1144 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, 1145 AppWidgetManager.INVALID_APPWIDGET_ID, 1146 UserHandle.USER_CURRENT); 1147 } 1148 1149 private void writeAppWidgets(int[] appWidgetIds) { 1150 Settings.Secure.putStringForUser(mContentResolver, 1151 Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, 1152 combineStrings(appWidgetIds, ","), 1153 UserHandle.USER_CURRENT); 1154 } 1155 1156 // TODO: log an error if this returns false 1157 public boolean addAppWidget(int widgetId, int index) { 1158 int[] widgets = getAppWidgets(); 1159 if (widgets == null) { 1160 return false; 1161 } 1162 if (index < 0 || index > widgets.length) { 1163 return false; 1164 } 1165 int[] newWidgets = new int[widgets.length + 1]; 1166 for (int i = 0, j = 0; i < newWidgets.length; i++) { 1167 if (index == i) { 1168 newWidgets[i] = widgetId; 1169 i++; 1170 } 1171 if (i < newWidgets.length) { 1172 newWidgets[i] = widgets[j]; 1173 j++; 1174 } 1175 } 1176 writeAppWidgets(newWidgets); 1177 return true; 1178 } 1179 1180 public boolean removeAppWidget(int widgetId) { 1181 int[] widgets = getAppWidgets(); 1182 1183 if (widgets.length == 0) { 1184 return false; 1185 } 1186 1187 int[] newWidgets = new int[widgets.length - 1]; 1188 for (int i = 0, j = 0; i < widgets.length; i++) { 1189 if (widgets[i] == widgetId) { 1190 // continue... 1191 } else if (j >= newWidgets.length) { 1192 // we couldn't find the widget 1193 return false; 1194 } else { 1195 newWidgets[j] = widgets[i]; 1196 j++; 1197 } 1198 } 1199 writeAppWidgets(newWidgets); 1200 return true; 1201 } 1202 1203 private long getLong(String secureSettingKey, long defaultValue) { 1204 try { 1205 return getLockSettings().getLong(secureSettingKey, defaultValue, 1206 getCurrentOrCallingUserId()); 1207 } catch (RemoteException re) { 1208 return defaultValue; 1209 } 1210 } 1211 1212 private void setLong(String secureSettingKey, long value) { 1213 setLong(secureSettingKey, value, getCurrentOrCallingUserId()); 1214 } 1215 1216 private void setLong(String secureSettingKey, long value, int userHandle) { 1217 try { 1218 getLockSettings().setLong(secureSettingKey, value, userHandle); 1219 } catch (RemoteException re) { 1220 // What can we do? 1221 Log.e(TAG, "Couldn't write long " + secureSettingKey + re); 1222 } 1223 } 1224 1225 private String getString(String secureSettingKey) { 1226 return getString(secureSettingKey, getCurrentOrCallingUserId()); 1227 } 1228 1229 private String getString(String secureSettingKey, int userHandle) { 1230 try { 1231 return getLockSettings().getString(secureSettingKey, null, userHandle); 1232 } catch (RemoteException re) { 1233 return null; 1234 } 1235 } 1236 1237 private void setString(String secureSettingKey, String value, int userHandle) { 1238 try { 1239 getLockSettings().setString(secureSettingKey, value, userHandle); 1240 } catch (RemoteException re) { 1241 // What can we do? 1242 Log.e(TAG, "Couldn't write string " + secureSettingKey + re); 1243 } 1244 } 1245 1246 public boolean isSecure() { 1247 long mode = getKeyguardStoredPasswordQuality(); 1248 final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 1249 final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 1250 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 1251 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 1252 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 1253 final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists() 1254 || isPassword && savedPasswordExists(); 1255 return secure; 1256 } 1257 1258 /** 1259 * Sets the emergency button visibility based on isEmergencyCallCapable(). 1260 * 1261 * If the emergency button is visible, sets the text on the emergency button 1262 * to indicate what action will be taken. 1263 * 1264 * If there's currently a call in progress, the button will take them to the call 1265 * @param button the button to update 1266 * @param the phone state: 1267 * {@link TelephonyManager#CALL_STATE_IDLE} 1268 * {@link TelephonyManager#CALL_STATE_RINGING} 1269 * {@link TelephonyManager#CALL_STATE_OFFHOOK} 1270 * @param shown indicates whether the given screen wants the emergency button to show at all 1271 * @param button 1272 * @param phoneState 1273 * @param shown shown if true; hidden if false 1274 * @param upperCase if true, converts button label string to upper case 1275 */ 1276 public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown, 1277 boolean showIcon) { 1278 if (isEmergencyCallCapable() && shown) { 1279 button.setVisibility(View.VISIBLE); 1280 } else { 1281 button.setVisibility(View.GONE); 1282 return; 1283 } 1284 1285 int textId; 1286 if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) { 1287 // show "return to call" text and show phone icon 1288 textId = R.string.lockscreen_return_to_call; 1289 int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0; 1290 button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0); 1291 } else { 1292 textId = R.string.lockscreen_emergency_call; 1293 int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0; 1294 button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0); 1295 } 1296 button.setText(textId); 1297 } 1298 1299 /** 1300 * Resumes a call in progress. Typically launched from the EmergencyCall button 1301 * on various lockscreens. 1302 * 1303 * @return true if we were able to tell InCallScreen to show. 1304 */ 1305 public boolean resumeCall() { 1306 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 1307 try { 1308 if (phone != null && phone.showCallScreen()) { 1309 return true; 1310 } 1311 } catch (RemoteException e) { 1312 // What can we do? 1313 } 1314 return false; 1315 } 1316 1317 private void finishBiometricWeak() { 1318 setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true); 1319 1320 // Launch intent to show final screen, this also 1321 // moves the temporary gallery to the actual gallery 1322 Intent intent = new Intent(); 1323 intent.setClassName("com.android.facelock", 1324 "com.android.facelock.SetupEndScreen"); 1325 mContext.startActivity(intent); 1326 } 1327 1328 public void setPowerButtonInstantlyLocks(boolean enabled) { 1329 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled); 1330 } 1331 1332 public boolean getPowerButtonInstantlyLocks() { 1333 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true); 1334 } 1335 1336 public static boolean isSafeModeEnabled() { 1337 try { 1338 return IWindowManager.Stub.asInterface( 1339 ServiceManager.getService("window")).isSafeModeEnabled(); 1340 } catch (RemoteException e) { 1341 // Shouldn't happen! 1342 } 1343 return false; 1344 } 1345 1346 /** 1347 * Determine whether the user has selected any non-system widgets in keyguard 1348 * 1349 * @return true if widgets have been selected 1350 */ 1351 public boolean hasWidgetsEnabledInKeyguard(int userid) { 1352 int widgets[] = getAppWidgets(userid); 1353 for (int i = 0; i < widgets.length; i++) { 1354 if (widgets[i] > 0) { 1355 return true; 1356 } 1357 } 1358 return false; 1359 } 1360 1361 public boolean getWidgetsEnabled() { 1362 return getWidgetsEnabled(getCurrentOrCallingUserId()); 1363 } 1364 1365 public boolean getWidgetsEnabled(int userId) { 1366 return getBoolean(LOCKSCREEN_WIDGETS_ENABLED, false, userId); 1367 } 1368 1369 public void setWidgetsEnabled(boolean enabled) { 1370 setWidgetsEnabled(enabled, getCurrentOrCallingUserId()); 1371 } 1372 1373 public void setWidgetsEnabled(boolean enabled, int userId) { 1374 setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId); 1375 } 1376 1377} 1378