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 com.android.internal.widget; 18 19 import android.Manifest; 20 import android.app.ActivityManagerNative; 21 import android.app.admin.DevicePolicyManager; 22 import android.appwidget.AppWidgetManager; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.os.Binder; 28 import android.os.IBinder; 29 import android.os.RemoteException; 30 import android.os.ServiceManager; 31 import android.os.SystemClock; 32 import android.os.UserHandle; 33 import android.os.storage.IMountService; 34 import android.provider.Settings; 35 import android.telephony.TelephonyManager; 36 import android.text.TextUtils; 37 import android.util.Log; 38 import android.view.IWindowManager; 39 import android.view.View; 40 import android.widget.Button; 41 42 import com.android.internal.R; 43 import com.android.internal.telephony.ITelephony; 44 import com.google.android.collect.Lists; 45 46 import java.security.MessageDigest; 47 import java.security.NoSuchAlgorithmException; 48 import java.security.SecureRandom; 49 import java.util.List; 50 51 /** 52 * Utilities for the lock pattern and its settings. 53 */ 54 public 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 setBoolean(PATTERN_EVER_CHOSEN_KEY, true); 503 if (!isFallback) { 504 deleteGallery(); 505 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 506 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 507 pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 508 } else { 509 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); 510 setLong(PASSWORD_TYPE_ALTERNATE_KEY, 511 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 512 finishBiometricWeak(); 513 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 514 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 515 } 516 } else { 517 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 518 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); 519 } 520 } catch (RemoteException re) { 521 Log.e(TAG, "Couldn't save lock pattern " + re); 522 } 523 } 524 525 public void setOwnerInfo(String info, int userId) { 526 setString(LOCK_SCREEN_OWNER_INFO, info, userId); 527 } 528 529 public void setOwnerInfoEnabled(boolean enabled) { 530 setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled); 531 } 532 533 public String getOwnerInfo(int userId) { 534 return getString(LOCK_SCREEN_OWNER_INFO); 535 } 536 537 public boolean isOwnerInfoEnabled() { 538 return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false); 539 } 540 541 /** 542 * Compute the password quality from the given password string. 543 */ 544 static public int computePasswordQuality(String password) { 545 boolean hasDigit = false; 546 boolean hasNonDigit = false; 547 final int len = password.length(); 548 for (int i = 0; i < len; i++) { 549 if (Character.isDigit(password.charAt(i))) { 550 hasDigit = true; 551 } else { 552 hasNonDigit = true; 553 } 554 } 555 556 if (hasNonDigit && hasDigit) { 557 return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 558 } 559 if (hasNonDigit) { 560 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 561 } 562 if (hasDigit) { 563 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 564 } 565 return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 566 } 567 568 /** Update the encryption password if it is enabled **/ 569 private void updateEncryptionPassword(String password) { 570 DevicePolicyManager dpm = getDevicePolicyManager(); 571 if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId()) 572 != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) { 573 return; 574 } 575 576 IBinder service = ServiceManager.getService("mount"); 577 if (service == null) { 578 Log.e(TAG, "Could not find the mount service to update the encryption password"); 579 return; 580 } 581 582 IMountService mountService = IMountService.Stub.asInterface(service); 583 try { 584 mountService.changeEncryptionPassword(password); 585 } catch (RemoteException e) { 586 Log.e(TAG, "Error changing encryption password", e); 587 } 588 } 589 590 /** 591 * Save a lock password. Does not ensure that the password is as good 592 * as the requested mode, but will adjust the mode to be as good as the 593 * pattern. 594 * @param password The password to save 595 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 596 */ 597 public void saveLockPassword(String password, int quality) { 598 this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId()); 599 } 600 601 /** 602 * Save a lock password. Does not ensure that the password is as good 603 * as the requested mode, but will adjust the mode to be as good as the 604 * pattern. 605 * @param password The password to save 606 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 607 * @param isFallback Specifies if this is a fallback to biometric weak 608 */ 609 public void saveLockPassword(String password, int quality, boolean isFallback) { 610 saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId()); 611 } 612 613 /** 614 * Save a lock password. Does not ensure that the password is as good 615 * as the requested mode, but will adjust the mode to be as good as the 616 * pattern. 617 * @param password The password to save 618 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 619 * @param isFallback Specifies if this is a fallback to biometric weak 620 * @param userHandle The userId of the user to change the password for 621 */ 622 public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { 623 try { 624 getLockSettings().setLockPassword(password, userHandle); 625 DevicePolicyManager dpm = getDevicePolicyManager(); 626 if (password != null) { 627 if (userHandle == UserHandle.USER_OWNER) { 628 // Update the encryption password. 629 updateEncryptionPassword(password); 630 } 631 632 int computedQuality = computePasswordQuality(password); 633 if (!isFallback) { 634 deleteGallery(); 635 setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle); 636 if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 637 int letters = 0; 638 int uppercase = 0; 639 int lowercase = 0; 640 int numbers = 0; 641 int symbols = 0; 642 int nonletter = 0; 643 for (int i = 0; i < password.length(); i++) { 644 char c = password.charAt(i); 645 if (c >= 'A' && c <= 'Z') { 646 letters++; 647 uppercase++; 648 } else if (c >= 'a' && c <= 'z') { 649 letters++; 650 lowercase++; 651 } else if (c >= '0' && c <= '9') { 652 numbers++; 653 nonletter++; 654 } else { 655 symbols++; 656 nonletter++; 657 } 658 } 659 dpm.setActivePasswordState(Math.max(quality, computedQuality), 660 password.length(), letters, uppercase, lowercase, 661 numbers, symbols, nonletter, userHandle); 662 } else { 663 // The password is not anything. 664 dpm.setActivePasswordState( 665 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 666 0, 0, 0, 0, 0, 0, 0, userHandle); 667 } 668 } else { 669 // Case where it's a fallback for biometric weak 670 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 671 userHandle); 672 setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality), 673 userHandle); 674 finishBiometricWeak(); 675 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 676 0, 0, 0, 0, 0, 0, 0, userHandle); 677 } 678 // Add the password to the password history. We assume all 679 // password 680 // hashes have the same length for simplicity of implementation. 681 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle); 682 if (passwordHistory == null) { 683 passwordHistory = new String(); 684 } 685 int passwordHistoryLength = getRequestedPasswordHistoryLength(); 686 if (passwordHistoryLength == 0) { 687 passwordHistory = ""; 688 } else { 689 byte[] hash = passwordToHash(password); 690 passwordHistory = new String(hash) + "," + passwordHistory; 691 // Cut it to contain passwordHistoryLength hashes 692 // and passwordHistoryLength -1 commas. 693 passwordHistory = passwordHistory.substring(0, Math.min(hash.length 694 * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory 695 .length())); 696 } 697 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); 698 } else { 699 dpm.setActivePasswordState( 700 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, 701 userHandle); 702 } 703 } catch (RemoteException re) { 704 // Cant do much 705 Log.e(TAG, "Unable to save lock password " + re); 706 } 707 } 708 709 /** 710 * Retrieves the quality mode we're in. 711 * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 712 * 713 * @return stored password quality 714 */ 715 public int getKeyguardStoredPasswordQuality() { 716 int quality = 717 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 718 // If the user has chosen to use weak biometric sensor, then return the backup locking 719 // method and treat biometric as a special case. 720 if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { 721 quality = 722 (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY, 723 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 724 } 725 return quality; 726 } 727 728 /** 729 * @return true if the lockscreen method is set to biometric weak 730 */ 731 public boolean usingBiometricWeak() { 732 int quality = 733 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 734 return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; 735 } 736 737 /** 738 * Deserialize a pattern. 739 * @param string The pattern serialized with {@link #patternToString} 740 * @return The pattern. 741 */ 742 public static List<LockPatternView.Cell> stringToPattern(String string) { 743 List<LockPatternView.Cell> result = Lists.newArrayList(); 744 745 final byte[] bytes = string.getBytes(); 746 for (int i = 0; i < bytes.length; i++) { 747 byte b = bytes[i]; 748 result.add(LockPatternView.Cell.of(b / 3, b % 3)); 749 } 750 return result; 751 } 752 753 /** 754 * Serialize a pattern. 755 * @param pattern The pattern. 756 * @return The pattern in string form. 757 */ 758 public static String patternToString(List<LockPatternView.Cell> pattern) { 759 if (pattern == null) { 760 return ""; 761 } 762 final int patternSize = pattern.size(); 763 764 byte[] res = new byte[patternSize]; 765 for (int i = 0; i < patternSize; i++) { 766 LockPatternView.Cell cell = pattern.get(i); 767 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn()); 768 } 769 return new String(res); 770 } 771 772 /* 773 * Generate an SHA-1 hash for the pattern. Not the most secure, but it is 774 * at least a second level of protection. First level is that the file 775 * is in a location only readable by the system process. 776 * @param pattern the gesture pattern. 777 * @return the hash of the pattern in a byte array. 778 */ 779 public static byte[] patternToHash(List<LockPatternView.Cell> pattern) { 780 if (pattern == null) { 781 return null; 782 } 783 784 final int patternSize = pattern.size(); 785 byte[] res = new byte[patternSize]; 786 for (int i = 0; i < patternSize; i++) { 787 LockPatternView.Cell cell = pattern.get(i); 788 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn()); 789 } 790 try { 791 MessageDigest md = MessageDigest.getInstance("SHA-1"); 792 byte[] hash = md.digest(res); 793 return hash; 794 } catch (NoSuchAlgorithmException nsa) { 795 return res; 796 } 797 } 798 799 private String getSalt() { 800 long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0); 801 if (salt == 0) { 802 try { 803 salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 804 setLong(LOCK_PASSWORD_SALT_KEY, salt); 805 Log.v(TAG, "Initialized lock password salt"); 806 } catch (NoSuchAlgorithmException e) { 807 // Throw an exception rather than storing a password we'll never be able to recover 808 throw new IllegalStateException("Couldn't get SecureRandom number", e); 809 } 810 } 811 return Long.toHexString(salt); 812 } 813 814 /* 815 * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. 816 * Not the most secure, but it is at least a second level of protection. First level is that 817 * the file is in a location only readable by the system process. 818 * @param password the gesture pattern. 819 * @return the hash of the pattern in a byte array. 820 */ 821 public byte[] passwordToHash(String password) { 822 if (password == null) { 823 return null; 824 } 825 String algo = null; 826 byte[] hashed = null; 827 try { 828 byte[] saltedPassword = (password + getSalt()).getBytes(); 829 byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); 830 byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); 831 hashed = (toHex(sha1) + toHex(md5)).getBytes(); 832 } catch (NoSuchAlgorithmException e) { 833 Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo); 834 } 835 return hashed; 836 } 837 838 private static String toHex(byte[] ary) { 839 final String hex = "0123456789ABCDEF"; 840 String ret = ""; 841 for (int i = 0; i < ary.length; i++) { 842 ret += hex.charAt((ary[i] >> 4) & 0xf); 843 ret += hex.charAt(ary[i] & 0xf); 844 } 845 return ret; 846 } 847 848 /** 849 * @return Whether the lock password is enabled, or if it is set as a backup for biometric weak 850 */ 851 public boolean isLockPasswordEnabled() { 852 long mode = getLong(PASSWORD_TYPE_KEY, 0); 853 long backupMode = getLong(PASSWORD_TYPE_ALTERNATE_KEY, 0); 854 final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 855 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 856 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 857 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 858 final boolean backupEnabled = backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 859 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 860 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 861 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 862 863 return savedPasswordExists() && (passwordEnabled || 864 (usingBiometricWeak() && backupEnabled)); 865 } 866 867 /** 868 * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak 869 */ 870 public boolean isLockPatternEnabled() { 871 final boolean backupEnabled = 872 getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) 873 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 874 875 return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false) 876 && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) 877 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING || 878 (usingBiometricWeak() && backupEnabled)); 879 } 880 881 /** 882 * @return Whether biometric weak lock is installed and that the front facing camera exists 883 */ 884 public boolean isBiometricWeakInstalled() { 885 // Check that it's installed 886 PackageManager pm = mContext.getPackageManager(); 887 try { 888 pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES); 889 } catch (PackageManager.NameNotFoundException e) { 890 return false; 891 } 892 893 // Check that the camera is enabled 894 if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) { 895 return false; 896 } 897 if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) { 898 return false; 899 } 900 901 902 return true; 903 } 904 905 /** 906 * Set whether biometric weak liveliness is enabled. 907 */ 908 public void setBiometricWeakLivelinessEnabled(boolean enabled) { 909 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L); 910 long newFlag; 911 if (enabled) { 912 newFlag = currentFlag | FLAG_BIOMETRIC_WEAK_LIVELINESS; 913 } else { 914 newFlag = currentFlag & ~FLAG_BIOMETRIC_WEAK_LIVELINESS; 915 } 916 setLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, newFlag); 917 } 918 919 /** 920 * @return Whether the biometric weak liveliness is enabled. 921 */ 922 public boolean isBiometricWeakLivelinessEnabled() { 923 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L); 924 return ((currentFlag & FLAG_BIOMETRIC_WEAK_LIVELINESS) != 0); 925 } 926 927 /** 928 * Set whether the lock pattern is enabled. 929 */ 930 public void setLockPatternEnabled(boolean enabled) { 931 setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled); 932 } 933 934 /** 935 * @return Whether the visible pattern is enabled. 936 */ 937 public boolean isVisiblePatternEnabled() { 938 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false); 939 } 940 941 /** 942 * Set whether the visible pattern is enabled. 943 */ 944 public void setVisiblePatternEnabled(boolean enabled) { 945 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled); 946 } 947 948 /** 949 * @return Whether tactile feedback for the pattern is enabled. 950 */ 951 public boolean isTactileFeedbackEnabled() { 952 return Settings.System.getIntForUser(mContentResolver, 953 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0; 954 } 955 956 /** 957 * Set and store the lockout deadline, meaning the user can't attempt his/her unlock 958 * pattern until the deadline has passed. 959 * @return the chosen deadline. 960 */ 961 public long setLockoutAttemptDeadline() { 962 final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS; 963 setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline); 964 return deadline; 965 } 966 967 /** 968 * @return The elapsed time in millis in the future when the user is allowed to 969 * attempt to enter his/her lock pattern, or 0 if the user is welcome to 970 * enter a pattern. 971 */ 972 public long getLockoutAttemptDeadline() { 973 final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L); 974 final long now = SystemClock.elapsedRealtime(); 975 if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) { 976 return 0L; 977 } 978 return deadline; 979 } 980 981 /** 982 * @return Whether the user is permanently locked out until they verify their 983 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed 984 * attempts. 985 */ 986 public boolean isPermanentlyLocked() { 987 return getBoolean(LOCKOUT_PERMANENT_KEY, false); 988 } 989 990 /** 991 * Set the state of whether the device is permanently locked, meaning the user 992 * must authenticate via other means. 993 * 994 * @param locked Whether the user is permanently locked out until they verify their 995 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed 996 * attempts. 997 */ 998 public void setPermanentlyLocked(boolean locked) { 999 setBoolean(LOCKOUT_PERMANENT_KEY, locked); 1000 } 1001 1002 public boolean isEmergencyCallCapable() { 1003 return mContext.getResources().getBoolean( 1004 com.android.internal.R.bool.config_voice_capable); 1005 } 1006 1007 public boolean isPukUnlockScreenEnable() { 1008 return mContext.getResources().getBoolean( 1009 com.android.internal.R.bool.config_enable_puk_unlock_screen); 1010 } 1011 1012 public boolean isEmergencyCallEnabledWhileSimLocked() { 1013 return mContext.getResources().getBoolean( 1014 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked); 1015 } 1016 1017 /** 1018 * @return A formatted string of the next alarm (for showing on the lock screen), 1019 * or null if there is no next alarm. 1020 */ 1021 public String getNextAlarm() { 1022 String nextAlarm = Settings.System.getStringForUser(mContentResolver, 1023 Settings.System.NEXT_ALARM_FORMATTED, UserHandle.USER_CURRENT); 1024 if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) { 1025 return null; 1026 } 1027 return nextAlarm; 1028 } 1029 1030 private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) { 1031 try { 1032 return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId); 1033 } catch (RemoteException re) { 1034 return defaultValue; 1035 } 1036 } 1037 1038 private boolean getBoolean(String secureSettingKey, boolean defaultValue) { 1039 return getBoolean(secureSettingKey, defaultValue, getCurrentOrCallingUserId()); 1040 } 1041 1042 private void setBoolean(String secureSettingKey, boolean enabled, int userId) { 1043 try { 1044 getLockSettings().setBoolean(secureSettingKey, enabled, userId); 1045 } catch (RemoteException re) { 1046 // What can we do? 1047 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re); 1048 } 1049 } 1050 1051 private void setBoolean(String secureSettingKey, boolean enabled) { 1052 setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId()); 1053 } 1054 1055 public int[] getAppWidgets() { 1056 return getAppWidgets(UserHandle.USER_CURRENT); 1057 } 1058 1059 private int[] getAppWidgets(int userId) { 1060 String appWidgetIdString = Settings.Secure.getStringForUser( 1061 mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, userId); 1062 String delims = ","; 1063 if (appWidgetIdString != null && appWidgetIdString.length() > 0) { 1064 String[] appWidgetStringIds = appWidgetIdString.split(delims); 1065 int[] appWidgetIds = new int[appWidgetStringIds.length]; 1066 for (int i = 0; i < appWidgetStringIds.length; i++) { 1067 String appWidget = appWidgetStringIds[i]; 1068 try { 1069 appWidgetIds[i] = Integer.decode(appWidget); 1070 } catch (NumberFormatException e) { 1071 Log.d(TAG, "Error when parsing widget id " + appWidget); 1072 return null; 1073 } 1074 } 1075 return appWidgetIds; 1076 } 1077 return new int[0]; 1078 } 1079 1080 private static String combineStrings(int[] list, String separator) { 1081 int listLength = list.length; 1082 1083 switch (listLength) { 1084 case 0: { 1085 return ""; 1086 } 1087 case 1: { 1088 return Integer.toString(list[0]); 1089 } 1090 } 1091 1092 int strLength = 0; 1093 int separatorLength = separator.length(); 1094 1095 String[] stringList = new String[list.length]; 1096 for (int i = 0; i < listLength; i++) { 1097 stringList[i] = Integer.toString(list[i]); 1098 strLength += stringList[i].length(); 1099 if (i < listLength - 1) { 1100 strLength += separatorLength; 1101 } 1102 } 1103 1104 StringBuilder sb = new StringBuilder(strLength); 1105 1106 for (int i = 0; i < listLength; i++) { 1107 sb.append(list[i]); 1108 if (i < listLength - 1) { 1109 sb.append(separator); 1110 } 1111 } 1112 1113 return sb.toString(); 1114 } 1115 1116 // appwidget used when appwidgets are disabled (we make an exception for 1117 // default clock widget) 1118 public void writeFallbackAppWidgetId(int appWidgetId) { 1119 Settings.Secure.putIntForUser(mContentResolver, 1120 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, 1121 appWidgetId, 1122 UserHandle.USER_CURRENT); 1123 } 1124 1125 // appwidget used when appwidgets are disabled (we make an exception for 1126 // default clock widget) 1127 public int getFallbackAppWidgetId() { 1128 return Settings.Secure.getIntForUser( 1129 mContentResolver, 1130 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, 1131 AppWidgetManager.INVALID_APPWIDGET_ID, 1132 UserHandle.USER_CURRENT); 1133 } 1134 1135 private void writeAppWidgets(int[] appWidgetIds) { 1136 Settings.Secure.putStringForUser(mContentResolver, 1137 Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, 1138 combineStrings(appWidgetIds, ","), 1139 UserHandle.USER_CURRENT); 1140 } 1141 1142 // TODO: log an error if this returns false 1143 public boolean addAppWidget(int widgetId, int index) { 1144 int[] widgets = getAppWidgets(); 1145 if (widgets == null) { 1146 return false; 1147 } 1148 if (index < 0 || index > widgets.length) { 1149 return false; 1150 } 1151 int[] newWidgets = new int[widgets.length + 1]; 1152 for (int i = 0, j = 0; i < newWidgets.length; i++) { 1153 if (index == i) { 1154 newWidgets[i] = widgetId; 1155 i++; 1156 } 1157 if (i < newWidgets.length) { 1158 newWidgets[i] = widgets[j]; 1159 j++; 1160 } 1161 } 1162 writeAppWidgets(newWidgets); 1163 return true; 1164 } 1165 1166 public boolean removeAppWidget(int widgetId) { 1167 int[] widgets = getAppWidgets(); 1168 1169 if (widgets.length == 0) { 1170 return false; 1171 } 1172 1173 int[] newWidgets = new int[widgets.length - 1]; 1174 for (int i = 0, j = 0; i < widgets.length; i++) { 1175 if (widgets[i] == widgetId) { 1176 // continue... 1177 } else if (j >= newWidgets.length) { 1178 // we couldn't find the widget 1179 return false; 1180 } else { 1181 newWidgets[j] = widgets[i]; 1182 j++; 1183 } 1184 } 1185 writeAppWidgets(newWidgets); 1186 return true; 1187 } 1188 1189 private long getLong(String secureSettingKey, long defaultValue) { 1190 try { 1191 return getLockSettings().getLong(secureSettingKey, defaultValue, 1192 getCurrentOrCallingUserId()); 1193 } catch (RemoteException re) { 1194 return defaultValue; 1195 } 1196 } 1197 1198 private void setLong(String secureSettingKey, long value) { 1199 setLong(secureSettingKey, value, getCurrentOrCallingUserId()); 1200 } 1201 1202 private void setLong(String secureSettingKey, long value, int userHandle) { 1203 try { 1204 getLockSettings().setLong(secureSettingKey, value, getCurrentOrCallingUserId()); 1205 } catch (RemoteException re) { 1206 // What can we do? 1207 Log.e(TAG, "Couldn't write long " + secureSettingKey + re); 1208 } 1209 } 1210 1211 private String getString(String secureSettingKey) { 1212 return getString(secureSettingKey, getCurrentOrCallingUserId()); 1213 } 1214 1215 private String getString(String secureSettingKey, int userHandle) { 1216 try { 1217 return getLockSettings().getString(secureSettingKey, null, userHandle); 1218 } catch (RemoteException re) { 1219 return null; 1220 } 1221 } 1222 1223 private void setString(String secureSettingKey, String value, int userHandle) { 1224 try { 1225 getLockSettings().setString(secureSettingKey, value, userHandle); 1226 } catch (RemoteException re) { 1227 // What can we do? 1228 Log.e(TAG, "Couldn't write string " + secureSettingKey + re); 1229 } 1230 } 1231 1232 public boolean isSecure() { 1233 long mode = getKeyguardStoredPasswordQuality(); 1234 final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 1235 final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 1236 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 1237 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 1238 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 1239 final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists() 1240 || isPassword && savedPasswordExists(); 1241 return secure; 1242 } 1243 1244 /** 1245 * Sets the emergency button visibility based on isEmergencyCallCapable(). 1246 * 1247 * If the emergency button is visible, sets the text on the emergency button 1248 * to indicate what action will be taken. 1249 * 1250 * If there's currently a call in progress, the button will take them to the call 1251 * @param button the button to update 1252 * @param the phone state: 1253 * {@link TelephonyManager#CALL_STATE_IDLE} 1254 * {@link TelephonyManager#CALL_STATE_RINGING} 1255 * {@link TelephonyManager#CALL_STATE_OFFHOOK} 1256 * @param shown indicates whether the given screen wants the emergency button to show at all 1257 * @param button 1258 * @param phoneState 1259 * @param shown shown if true; hidden if false 1260 * @param upperCase if true, converts button label string to upper case 1261 */ 1262 public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown, 1263 boolean showIcon) { 1264 if (isEmergencyCallCapable() && shown) { 1265 button.setVisibility(View.VISIBLE); 1266 } else { 1267 button.setVisibility(View.GONE); 1268 return; 1269 } 1270 1271 int textId; 1272 if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) { 1273 // show "return to call" text and show phone icon 1274 textId = R.string.lockscreen_return_to_call; 1275 int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0; 1276 button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0); 1277 } else { 1278 textId = R.string.lockscreen_emergency_call; 1279 int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0; 1280 button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0); 1281 } 1282 button.setText(textId); 1283 } 1284 1285 /** 1286 * Resumes a call in progress. Typically launched from the EmergencyCall button 1287 * on various lockscreens. 1288 * 1289 * @return true if we were able to tell InCallScreen to show. 1290 */ 1291 public boolean resumeCall() { 1292 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 1293 try { 1294 if (phone != null && phone.showCallScreen()) { 1295 return true; 1296 } 1297 } catch (RemoteException e) { 1298 // What can we do? 1299 } 1300 return false; 1301 } 1302 1303 private void finishBiometricWeak() { 1304 setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true); 1305 1306 // Launch intent to show final screen, this also 1307 // moves the temporary gallery to the actual gallery 1308 Intent intent = new Intent(); 1309 intent.setClassName("com.android.facelock", 1310 "com.android.facelock.SetupEndScreen"); 1311 mContext.startActivity(intent); 1312 } 1313 1314 public void setPowerButtonInstantlyLocks(boolean enabled) { 1315 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled); 1316 } 1317 1318 public boolean getPowerButtonInstantlyLocks() { 1319 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true); 1320 } 1321 1322 public static boolean isSafeModeEnabled() { 1323 try { 1324 return IWindowManager.Stub.asInterface( 1325 ServiceManager.getService("window")).isSafeModeEnabled(); 1326 } catch (RemoteException e) { 1327 // Shouldn't happen! 1328 } 1329 return false; 1330 } 1331 1332 /** 1333 * Determine whether the user has selected any non-system widgets in keyguard 1334 * 1335 * @return true if widgets have been selected 1336 */ 1337 public boolean hasWidgetsEnabledInKeyguard(int userid) { 1338 int widgets[] = getAppWidgets(userid); 1339 for (int i = 0; i < widgets.length; i++) { 1340 if (widgets[i] > 0) { 1341 return true; 1342 } 1343 } 1344 return false; 1345 } 1346 1347 public boolean getWidgetsEnabled() { 1348 return getWidgetsEnabled(getCurrentOrCallingUserId()); 1349 } 1350 1351 public boolean getWidgetsEnabled(int userId) { 1352 return getBoolean(LOCKSCREEN_WIDGETS_ENABLED, false, userId); 1353 } 1354 1355 public void setWidgetsEnabled(boolean enabled) { 1356 setWidgetsEnabled(enabled, getCurrentOrCallingUserId()); 1357 } 1358 1359 public void setWidgetsEnabled(boolean enabled, int userId) { 1360 setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId); 1361 } 1362 1363 } 1364