blob: d14b1ee1a13aa6a2d9de22a48da033ba7942654f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Jason parksf7b3cd42011-01-27 09:28:25 -060019import com.android.internal.R;
20import com.android.internal.telephony.ITelephony;
21import com.google.android.collect.Lists;
22
Amith Yamasani4b4b9542012-09-14 13:36:29 -070023import android.app.ActivityManagerNative;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080024import android.app.admin.DevicePolicyManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.ContentResolver;
Jim Miller31f90b62010-01-20 13:35:20 -080026import android.content.Context;
Steven Ross329979c2011-09-28 11:42:56 -040027import android.content.Intent;
Danielle Millett58396982011-09-30 13:55:07 -040028import android.content.pm.PackageManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -070029import android.os.Binder;
Adam Cohenf7522022012-10-03 20:03:18 -070030import android.os.Bundle;
Jason parksf7b3cd42011-01-27 09:28:25 -060031import android.os.IBinder;
Amith Yamasani52c489c2012-03-28 11:42:42 -070032import android.os.Process;
Jim Miller69ac9882010-02-24 15:35:05 -080033import android.os.RemoteException;
34import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070036import android.os.UserHandle;
Jason parksf7b3cd42011-01-27 09:28:25 -060037import android.os.storage.IMountService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.provider.Settings;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070039import android.security.KeyStore;
Jim Miller69ac9882010-02-24 15:35:05 -080040import android.telephony.TelephonyManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.text.TextUtils;
42import android.util.Log;
John Wang0f7b3f82011-05-31 11:20:55 -070043import android.view.View;
Jim Miller69ac9882010-02-24 15:35:05 -080044import android.widget.Button;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045
Brian Carlstrom929a1c22011-02-01 21:54:09 -080046import java.security.MessageDigest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import java.security.NoSuchAlgorithmException;
Jim Miller11b019d2010-01-20 16:34:45 -080048import java.security.SecureRandom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import java.util.List;
50
51/**
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070052 * Utilities for the lock pattern and its settings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 */
54public class LockPatternUtils {
55
Jim Millercb3521e2011-10-03 20:42:26 -070056 private static final String OPTION_ENABLE_FACELOCK = "enable_facelock";
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 private static final String TAG = "LockPatternUtils";
Jim Miller69aa4a92009-12-22 19:03:28 -080059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 /**
61 * The maximum number of incorrect attempts before the user is prevented
62 * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
63 */
64 public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5;
65
66 /**
67 * The number of incorrect attempts before which we fall back on an alternative
68 * method of verifying the user, and resetting their lock pattern.
69 */
70 public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
71
72 /**
73 * How long the user is prevented from trying again after entering the
74 * wrong pattern too many times.
75 */
76 public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L;
77
78 /**
79 * The interval of the countdown for showing progress of the lockout.
80 */
81 public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
82
Jim Miller4f369952011-08-19 18:29:22 -070083
84 /**
85 * This dictates when we start telling the user that continued failed attempts will wipe
86 * their device.
87 */
88 public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
89
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 /**
91 * The minimum number of dots in a valid pattern.
92 */
93 public static final int MIN_LOCK_PATTERN_SIZE = 4;
94
95 /**
96 * The minimum number of dots the user must include in a wrong pattern
97 * attempt for it to be counted against the counts that affect
98 * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
99 */
Jim Miller4f369952011-08-19 18:29:22 -0700100 public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101
Danielle Millett925a7d82012-03-19 18:02:20 -0400102 /**
Adam Cohenf7522022012-10-03 20:03:18 -0700103 * Tells the keyguard to show the user switcher when the keyguard is created.
104 */
105 public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher";
106
107 /**
108 * Tells the keyguard to show the security challenge when the keyguard is created.
109 */
110 public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge";
111
112 /**
113 * Options used to lock the device upon user switch.
114 */
115 public static final Bundle USER_SWITCH_LOCK_OPTIONS = new Bundle();
116
117 static {
118 USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_USER_SWITCHER, true);
119 USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
120 }
121
122 /**
Danielle Millett925a7d82012-03-19 18:02:20 -0400123 * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
124 * be used
125 */
126 public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
127
Amith Yamasani52c489c2012-03-28 11:42:42 -0700128 protected final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
129 protected final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
130 protected final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
Jim Miller69aa4a92009-12-22 19:03:28 -0800131 public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
Jim Miller6edf2632011-09-05 16:03:14 -0700132 public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
Amith Yamasani52c489c2012-03-28 11:42:42 -0700133 protected final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
134 protected final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
135 protected final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
Jim Miller6edf2632011-09-05 16:03:14 -0700136 public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
137 = "lockscreen.biometric_weak_fallback";
Danielle Millett7a072192011-10-03 17:36:01 -0400138 public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
139 = "lockscreen.biometricweakeverchosen";
Jim Millera4edd152012-01-06 18:24:04 -0800140 public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
141 = "lockscreen.power_button_instantly_locks";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Amith Yamasani52c489c2012-03-28 11:42:42 -0700143 protected final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700144
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800145 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private final ContentResolver mContentResolver;
Jim Miller31f90b62010-01-20 13:35:20 -0800147 private DevicePolicyManager mDevicePolicyManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700148 private ILockSettings mLockSettingsService;
Jim Milleree82f8f2012-10-01 16:26:18 -0700149
150 // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
151 private static volatile int sCurrentUserId = UserHandle.USER_NULL;
Dianne Hackbornde4c26f2011-07-17 13:42:47 -0700152
Jim Millercd709882010-03-25 18:24:02 -0700153 public DevicePolicyManager getDevicePolicyManager() {
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800154 if (mDevicePolicyManager == null) {
155 mDevicePolicyManager =
156 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
157 if (mDevicePolicyManager == null) {
158 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
159 new IllegalStateException("Stack trace:"));
160 }
161 }
162 return mDevicePolicyManager;
163 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 /**
166 * @param contentResolver Used to look up and save settings.
167 */
Jim Miller31f90b62010-01-20 13:35:20 -0800168 public LockPatternUtils(Context context) {
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800169 mContext = context;
Jim Miller31f90b62010-01-20 13:35:20 -0800170 mContentResolver = context.getContentResolver();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700171 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800172
Amith Yamasani52c489c2012-03-28 11:42:42 -0700173 private ILockSettings getLockSettings() {
174 if (mLockSettingsService == null) {
175 mLockSettingsService = ILockSettings.Stub.asInterface(
176 (IBinder) ServiceManager.getService("lock_settings"));
Brad Fitzpatrick90881002010-08-23 18:30:08 -0700177 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700178 return mLockSettingsService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 }
180
Jim Miller31f90b62010-01-20 13:35:20 -0800181 public int getRequestedMinimumPasswordLength() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700182 return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800183 }
184
Jim Miller31f90b62010-01-20 13:35:20 -0800185 /**
186 * Gets the device policy password mode. If the mode is non-specific, returns
187 * MODE_PATTERN which allows the user to choose anything.
Jim Miller31f90b62010-01-20 13:35:20 -0800188 */
Jim Millercd709882010-03-25 18:24:02 -0700189 public int getRequestedPasswordQuality() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700190 return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800191 }
192
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700193 public int getRequestedPasswordHistoryLength() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700194 return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId());
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700195 }
196
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700197 public int getRequestedPasswordMinimumLetters() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700198 return getDevicePolicyManager().getPasswordMinimumLetters(null,
199 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700200 }
201
202 public int getRequestedPasswordMinimumUpperCase() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700203 return getDevicePolicyManager().getPasswordMinimumUpperCase(null,
204 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700205 }
206
207 public int getRequestedPasswordMinimumLowerCase() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700208 return getDevicePolicyManager().getPasswordMinimumLowerCase(null,
209 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700210 }
211
212 public int getRequestedPasswordMinimumNumeric() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700213 return getDevicePolicyManager().getPasswordMinimumNumeric(null,
214 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700215 }
216
217 public int getRequestedPasswordMinimumSymbols() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700218 return getDevicePolicyManager().getPasswordMinimumSymbols(null,
219 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700220 }
221
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700222 public int getRequestedPasswordMinimumNonLetter() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700223 return getDevicePolicyManager().getPasswordMinimumNonLetter(null,
224 getCurrentOrCallingUserId());
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700225 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700226
Jim Miller31f90b62010-01-20 13:35:20 -0800227 /**
228 * Returns the actual password mode, as set by keyguard after updating the password.
229 *
230 * @return
231 */
Jim Miller31f90b62010-01-20 13:35:20 -0800232 public void reportFailedPasswordAttempt() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700233 getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800234 }
235
236 public void reportSuccessfulPasswordAttempt() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700237 getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800238 }
239
Amith Yamasani52c489c2012-03-28 11:42:42 -0700240 public void setCurrentUser(int userId) {
Jim Milleree82f8f2012-10-01 16:26:18 -0700241 sCurrentUserId = userId;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700242 }
243
Amith Yamasanif882f1a2012-04-10 15:13:39 -0700244 public int getCurrentUser() {
Jim Milleree82f8f2012-10-01 16:26:18 -0700245 if (sCurrentUserId != UserHandle.USER_NULL) {
Jim Miller25645d82012-09-21 14:47:54 -0700246 // Someone is regularly updating using setCurrentUser() use that value.
Jim Milleree82f8f2012-10-01 16:26:18 -0700247 return sCurrentUserId;
Jim Miller25645d82012-09-21 14:47:54 -0700248 }
249 try {
250 return ActivityManagerNative.getDefault().getCurrentUser().id;
251 } catch (RemoteException re) {
252 return UserHandle.USER_OWNER;
Amith Yamasanif882f1a2012-04-10 15:13:39 -0700253 }
254 }
255
Amith Yamasani52c489c2012-03-28 11:42:42 -0700256 public void removeUser(int userId) {
Jim Miller25645d82012-09-21 14:47:54 -0700257 try {
258 getLockSettings().removeUser(userId);
259 } catch (RemoteException re) {
260 Log.e(TAG, "Couldn't remove lock settings for user " + userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700261 }
262 }
263
264 private int getCurrentOrCallingUserId() {
265 int callingUid = Binder.getCallingUid();
266 if (callingUid == android.os.Process.SYSTEM_UID) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700267 // TODO: This is a little inefficient. See if all users of this are able to
268 // handle USER_CURRENT and pass that instead.
269 return getCurrentUser();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700270 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700271 return UserHandle.getUserId(callingUid);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700272 }
273 }
274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 /**
276 * Check to see if a pattern matches the saved pattern. If no pattern exists,
277 * always returns true.
278 * @param pattern The pattern to check.
Jim Miller69aa4a92009-12-22 19:03:28 -0800279 * @return Whether the pattern matches the stored one.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 */
281 public boolean checkPattern(List<LockPatternView.Cell> pattern) {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700282 final int userId = getCurrentOrCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 try {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700284 final boolean matched = getLockSettings().checkPattern(patternToHash(pattern), userId);
285 if (matched && (userId == UserHandle.USER_OWNER)) {
286 KeyStore.getInstance().password(patternToString(pattern));
287 }
288 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700289 } catch (RemoteException re) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 return true;
291 }
292 }
293
294 /**
Jim Miller69aa4a92009-12-22 19:03:28 -0800295 * Check to see if a password matches the saved password. If no password exists,
296 * always returns true.
297 * @param password The password to check.
298 * @return Whether the password matches the stored one.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 */
Jim Miller69aa4a92009-12-22 19:03:28 -0800300 public boolean checkPassword(String password) {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700301 final int userId = getCurrentOrCallingUserId();
Jim Miller69aa4a92009-12-22 19:03:28 -0800302 try {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700303 final boolean matched = getLockSettings().checkPassword(passwordToHash(password),
304 userId);
305 if (matched && (userId == UserHandle.USER_OWNER)) {
306 KeyStore.getInstance().password(password);
307 }
308 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700309 } catch (RemoteException re) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800310 return true;
311 }
312 }
313
314 /**
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700315 * Check to see if a password matches any of the passwords stored in the
316 * password history.
317 *
318 * @param password The password to check.
319 * @return Whether the password matches any in the history.
320 */
321 public boolean checkPasswordHistory(String password) {
322 String passwordHashString = new String(passwordToHash(password));
323 String passwordHistory = getString(PASSWORD_HISTORY_KEY);
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700324 if (passwordHistory == null) {
325 return false;
326 }
327 // Password History may be too long...
328 int passwordHashLength = passwordHashString.length();
329 int passwordHistoryLength = getRequestedPasswordHistoryLength();
330 if(passwordHistoryLength == 0) {
331 return false;
332 }
333 int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
334 + passwordHistoryLength - 1;
335 if (passwordHistory.length() > neededPasswordHistoryLength) {
336 passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
337 }
338 return passwordHistory.contains(passwordHashString);
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700339 }
340
341 /**
Jim Miller69aa4a92009-12-22 19:03:28 -0800342 * Check to see if the user has stored a lock pattern.
343 * @return Whether a saved pattern exists.
344 */
345 public boolean savedPatternExists() {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700346 try {
347 return getLockSettings().havePattern(getCurrentOrCallingUserId());
348 } catch (RemoteException re) {
349 return false;
350 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800351 }
352
353 /**
354 * Check to see if the user has stored a lock pattern.
355 * @return Whether a saved pattern exists.
356 */
357 public boolean savedPasswordExists() {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700358 try {
359 return getLockSettings().havePassword(getCurrentOrCallingUserId());
360 } catch (RemoteException re) {
361 return false;
362 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800363 }
364
365 /**
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700366 * Return true if the user has ever chosen a pattern. This is true even if the pattern is
367 * currently cleared.
368 *
369 * @return True if the user has ever chosen a pattern.
370 */
371 public boolean isPatternEverChosen() {
Jim Millera4edd152012-01-06 18:24:04 -0800372 return getBoolean(PATTERN_EVER_CHOSEN_KEY, false);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700373 }
374
375 /**
Danielle Millett7a072192011-10-03 17:36:01 -0400376 * Return true if the user has ever chosen biometric weak. This is true even if biometric
377 * weak is not current set.
378 *
379 * @return True if the user has ever chosen biometric weak.
380 */
381 public boolean isBiometricWeakEverChosen() {
Jim Millera4edd152012-01-06 18:24:04 -0800382 return getBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, false);
Danielle Millett7a072192011-10-03 17:36:01 -0400383 }
384
385 /**
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700386 * Used by device policy manager to validate the current password
387 * information it has.
388 */
389 public int getActivePasswordQuality() {
Jim Millercd709882010-03-25 18:24:02 -0700390 int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Danielle Millettc8fb5322011-10-04 12:18:51 -0400391 // Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to
392 // return biometric_weak if that is being used instead of the backup
393 int quality =
394 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
395 switch (quality) {
Jim Millercd709882010-03-25 18:24:02 -0700396 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700397 if (isLockPatternEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700398 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700399 }
Jim Millercd709882010-03-25 18:24:02 -0700400 break;
Danielle Millettc8fb5322011-10-04 12:18:51 -0400401 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
402 if (isBiometricWeakInstalled()) {
403 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
404 }
405 break;
Jim Millercd709882010-03-25 18:24:02 -0700406 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700407 if (isLockPasswordEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700408 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700409 }
Jim Millercd709882010-03-25 18:24:02 -0700410 break;
411 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700412 if (isLockPasswordEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700413 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700414 }
Jim Millercd709882010-03-25 18:24:02 -0700415 break;
416 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
417 if (isLockPasswordEnabled()) {
418 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
419 }
420 break;
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700421 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
422 if (isLockPasswordEnabled()) {
423 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
424 }
425 break;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700426 }
Danielle Millettc8fb5322011-10-04 12:18:51 -0400427
Jim Millercd709882010-03-25 18:24:02 -0700428 return activePasswordQuality;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700429 }
Jim Millercd709882010-03-25 18:24:02 -0700430
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700431 /**
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800432 * Clear any lock pattern or password.
433 */
Steven Ross329979c2011-09-28 11:42:56 -0400434 public void clearLock(boolean isFallback) {
435 if(!isFallback) deleteGallery();
Jim Millercd709882010-03-25 18:24:02 -0700436 saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800437 setLockPatternEnabled(false);
438 saveLockPattern(null);
Jim Miller93708af12012-01-25 18:26:12 -0800439 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
Jim Miller6edf2632011-09-05 16:03:14 -0700440 setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800441 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800442
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800443 /**
Jim Miller2a98a4c2010-11-19 18:49:26 -0800444 * Disable showing lock screen at all when the DevicePolicyManager allows it.
445 * This is only meaningful if pattern, pin or password are not set.
446 *
447 * @param disable Disables lock screen when true
448 */
449 public void setLockScreenDisabled(boolean disable) {
450 setLong(DISABLE_LOCKSCREEN_KEY, disable ? 1 : 0);
451 }
452
453 /**
454 * Determine if LockScreen can be disabled. This is used, for example, to tell if we should
455 * show LockScreen or go straight to the home screen.
456 *
457 * @return true if lock screen is can be disabled
458 */
459 public boolean isLockScreenDisabled() {
460 return !isSecure() && getLong(DISABLE_LOCKSCREEN_KEY, 0) != 0;
461 }
462
463 /**
Steven Ross3553c292011-09-30 15:48:40 -0400464 * Calls back SetupFaceLock to delete the temporary gallery file
Steven Ross329979c2011-09-28 11:42:56 -0400465 */
466 public void deleteTempGallery() {
Danielle Millett574e49e2012-03-27 16:17:10 -0400467 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
Steven Ross3553c292011-09-30 15:48:40 -0400468 intent.putExtra("deleteTempGallery", true);
Danielle Millett574e49e2012-03-27 16:17:10 -0400469 mContext.sendBroadcast(intent);
Steven Ross329979c2011-09-28 11:42:56 -0400470 }
471
472 /**
473 * Calls back SetupFaceLock to delete the gallery file when the lock type is changed
474 */
475 void deleteGallery() {
Danielle Millett58396982011-09-30 13:55:07 -0400476 if(usingBiometricWeak()) {
Danielle Millett574e49e2012-03-27 16:17:10 -0400477 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
Steven Ross329979c2011-09-28 11:42:56 -0400478 intent.putExtra("deleteGallery", true);
Danielle Millett574e49e2012-03-27 16:17:10 -0400479 mContext.sendBroadcast(intent);
Steven Ross329979c2011-09-28 11:42:56 -0400480 }
481 }
482
483 /**
Jim Miller6edf2632011-09-05 16:03:14 -0700484 * Save a lock pattern.
485 * @param pattern The new pattern to save.
Danielle Millett2364a222011-12-21 17:02:32 -0500486 */
487 public void saveLockPattern(List<LockPatternView.Cell> pattern) {
488 this.saveLockPattern(pattern, false);
489 }
490
491 /**
492 * Save a lock pattern.
493 * @param pattern The new pattern to save.
Jim Miller6edf2632011-09-05 16:03:14 -0700494 * @param isFallback Specifies if this is a fallback to biometric weak
495 */
496 public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 // Compute the hash
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700498 final byte[] hash = LockPatternUtils.patternToHash(pattern);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 try {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700500 getLockSettings().setLockPattern(hash, getCurrentOrCallingUserId());
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800501 DevicePolicyManager dpm = getDevicePolicyManager();
Brian Carlstrome2afc242011-06-02 16:21:55 -0700502 KeyStore keyStore = KeyStore.getInstance();
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800503 if (pattern != null) {
Brian Carlstrome2afc242011-06-02 16:21:55 -0700504 keyStore.password(patternToString(pattern));
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800505 setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
Jim Miller6edf2632011-09-05 16:03:14 -0700506 if (!isFallback) {
Steven Ross329979c2011-09-28 11:42:56 -0400507 deleteGallery();
Jim Miller6edf2632011-09-05 16:03:14 -0700508 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Danielle Millett2364a222011-12-21 17:02:32 -0500509 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700510 pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
Jim Miller6edf2632011-09-05 16:03:14 -0700511 } else {
512 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
513 setLong(PASSWORD_TYPE_ALTERNATE_KEY,
514 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Danielle Millett044a0a72011-11-07 15:42:12 -0500515 finishBiometricWeak();
Danielle Millett2364a222011-12-21 17:02:32 -0500516 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700517 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
Jim Miller6edf2632011-09-05 16:03:14 -0700518 }
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800519 } else {
Brian Carlstrome2afc242011-06-02 16:21:55 -0700520 if (keyStore.isEmpty()) {
521 keyStore.reset();
522 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700523 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700524 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800525 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700526 } catch (RemoteException re) {
527 Log.e(TAG, "Couldn't save lock pattern " + re);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 }
529 }
530
531 /**
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700532 * Compute the password quality from the given password string.
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800533 */
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700534 static public int computePasswordQuality(String password) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800535 boolean hasDigit = false;
536 boolean hasNonDigit = false;
537 final int len = password.length();
538 for (int i = 0; i < len; i++) {
539 if (Character.isDigit(password.charAt(i))) {
540 hasDigit = true;
541 } else {
542 hasNonDigit = true;
543 }
544 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800545
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700546 if (hasNonDigit && hasDigit) {
547 return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800548 }
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800549 if (hasNonDigit) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700550 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800551 }
552 if (hasDigit) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700553 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800554 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700555 return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800556 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800557
Jason parksf7b3cd42011-01-27 09:28:25 -0600558 /** Update the encryption password if it is enabled **/
559 private void updateEncryptionPassword(String password) {
560 DevicePolicyManager dpm = getDevicePolicyManager();
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700561 if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId())
562 != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
Jason parksf7b3cd42011-01-27 09:28:25 -0600563 return;
564 }
565
566 IBinder service = ServiceManager.getService("mount");
567 if (service == null) {
568 Log.e(TAG, "Could not find the mount service to update the encryption password");
569 return;
570 }
571
572 IMountService mountService = IMountService.Stub.asInterface(service);
573 try {
574 mountService.changeEncryptionPassword(password);
575 } catch (RemoteException e) {
576 Log.e(TAG, "Error changing encryption password", e);
577 }
578 }
579
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800580 /**
Jim Millercd709882010-03-25 18:24:02 -0700581 * Save a lock password. Does not ensure that the password is as good
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800582 * as the requested mode, but will adjust the mode to be as good as the
583 * pattern.
Jim Miller69aa4a92009-12-22 19:03:28 -0800584 * @param password The password to save
Jim Millercd709882010-03-25 18:24:02 -0700585 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
Jim Miller69aa4a92009-12-22 19:03:28 -0800586 */
Jim Millercd709882010-03-25 18:24:02 -0700587 public void saveLockPassword(String password, int quality) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700588 this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId());
Jim Miller6edf2632011-09-05 16:03:14 -0700589 }
590
591 /**
592 * Save a lock password. Does not ensure that the password is as good
593 * as the requested mode, but will adjust the mode to be as good as the
594 * pattern.
595 * @param password The password to save
596 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
597 * @param isFallback Specifies if this is a fallback to biometric weak
598 */
599 public void saveLockPassword(String password, int quality, boolean isFallback) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700600 saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId());
601 }
602
603 /**
604 * Save a lock password. Does not ensure that the password is as good
605 * as the requested mode, but will adjust the mode to be as good as the
606 * pattern.
607 * @param password The password to save
608 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
609 * @param isFallback Specifies if this is a fallback to biometric weak
610 * @param userHandle The userId of the user to change the password for
611 */
612 public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800613 // Compute the hash
Jim Miller11b019d2010-01-20 16:34:45 -0800614 final byte[] hash = passwordToHash(password);
Jim Miller69aa4a92009-12-22 19:03:28 -0800615 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700616 getLockSettings().setLockPassword(hash, userHandle);
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800617 DevicePolicyManager dpm = getDevicePolicyManager();
Brian Carlstrome2afc242011-06-02 16:21:55 -0700618 KeyStore keyStore = KeyStore.getInstance();
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800619 if (password != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700620 if (userHandle == UserHandle.USER_OWNER) {
621 // Update the encryption password.
622 updateEncryptionPassword(password);
Jason parksf7b3cd42011-01-27 09:28:25 -0600623
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700624 // Update the keystore password
625 keyStore.password(password);
626 }
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700627
Jim Millercd709882010-03-25 18:24:02 -0700628 int computedQuality = computePasswordQuality(password);
Jim Miller6edf2632011-09-05 16:03:14 -0700629 if (!isFallback) {
Steven Ross329979c2011-09-28 11:42:56 -0400630 deleteGallery();
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700631 setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500632 if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
633 int letters = 0;
634 int uppercase = 0;
635 int lowercase = 0;
636 int numbers = 0;
637 int symbols = 0;
638 int nonletter = 0;
639 for (int i = 0; i < password.length(); i++) {
640 char c = password.charAt(i);
641 if (c >= 'A' && c <= 'Z') {
642 letters++;
643 uppercase++;
644 } else if (c >= 'a' && c <= 'z') {
645 letters++;
646 lowercase++;
647 } else if (c >= '0' && c <= '9') {
648 numbers++;
649 nonletter++;
650 } else {
651 symbols++;
652 nonletter++;
653 }
654 }
655 dpm.setActivePasswordState(Math.max(quality, computedQuality),
656 password.length(), letters, uppercase, lowercase,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700657 numbers, symbols, nonletter, userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500658 } else {
659 // The password is not anything.
660 dpm.setActivePasswordState(
661 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700662 0, 0, 0, 0, 0, 0, 0, userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500663 }
Jim Miller6edf2632011-09-05 16:03:14 -0700664 } else {
Danielle Millett2364a222011-12-21 17:02:32 -0500665 // Case where it's a fallback for biometric weak
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700666 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
667 userHandle);
668 setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality),
669 userHandle);
Danielle Millett044a0a72011-11-07 15:42:12 -0500670 finishBiometricWeak();
Danielle Millett2364a222011-12-21 17:02:32 -0500671 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700672 0, 0, 0, 0, 0, 0, 0, userHandle);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700673 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700674 // Add the password to the password history. We assume all
675 // password
676 // hashes have the same length for simplicity of implementation.
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700677 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700678 if (passwordHistory == null) {
679 passwordHistory = new String();
680 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700681 int passwordHistoryLength = getRequestedPasswordHistoryLength();
682 if (passwordHistoryLength == 0) {
683 passwordHistory = "";
684 } else {
685 passwordHistory = new String(hash) + "," + passwordHistory;
686 // Cut it to contain passwordHistoryLength hashes
687 // and passwordHistoryLength -1 commas.
688 passwordHistory = passwordHistory.substring(0, Math.min(hash.length
689 * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
690 .length()));
691 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700692 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800693 } else {
Brian Carlstrome2afc242011-06-02 16:21:55 -0700694 // Conditionally reset the keystore if empty. If
695 // non-empty, we are just switching key guard type
696 if (keyStore.isEmpty()) {
697 keyStore.reset();
698 }
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800699 dpm.setActivePasswordState(
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700700 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
701 userHandle);
Jim Miller31f90b62010-01-20 13:35:20 -0800702 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700703 } catch (RemoteException re) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800704 // Cant do much
Amith Yamasani52c489c2012-03-28 11:42:42 -0700705 Log.e(TAG, "Unable to save lock password " + re);
Jim Miller69aa4a92009-12-22 19:03:28 -0800706 }
707 }
708
Jim Millercd709882010-03-25 18:24:02 -0700709 /**
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() {
Jim Miller6edf2632011-09-05 16:03:14 -0700716 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
Danielle Millett58396982011-09-30 13:55:07 -0400728 /**
729 * @return true if the lockscreen method is set to biometric weak
730 */
Jim Miller6edf2632011-09-05 16:03:14 -0700731 public boolean usingBiometricWeak() {
732 int quality =
733 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
734 return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
Jim Miller69aa4a92009-12-22 19:03:28 -0800735 }
736
737 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 * 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 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 /*
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 */
Jim Miller69aa4a92009-12-22 19:03:28 -0800779 private static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 if (pattern == null) {
781 return null;
782 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 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
Jim Miller11b019d2010-01-20 16:34:45 -0800799 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
Jim Miller69aa4a92009-12-22 19:03:28 -0800814 /*
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 */
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700821 public byte[] passwordToHash(String password) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800822 if (password == null) {
823 return null;
824 }
825 String algo = null;
826 byte[] hashed = null;
827 try {
Jim Miller11b019d2010-01-20 16:34:45 -0800828 byte[] saltedPassword = (password + getSalt()).getBytes();
Jim Miller69aa4a92009-12-22 19:03:28 -0800829 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 /**
Danielle Millett73da5fe2011-09-13 16:20:05 -0400849 * @return Whether the lock password is enabled, or if it is set as a backup for biometric weak
Jim Miller69aa4a92009-12-22 19:03:28 -0800850 */
851 public boolean isLockPasswordEnabled() {
852 long mode = getLong(PASSWORD_TYPE_KEY, 0);
Danielle Millett73da5fe2011-09-13 16:20:05 -0400853 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 ||
Danielle Millett58396982011-09-30 13:55:07 -0400864 (usingBiometricWeak() && backupEnabled));
Jim Miller69aa4a92009-12-22 19:03:28 -0800865 }
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 /**
Danielle Millett73da5fe2011-09-13 16:20:05 -0400868 * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 */
870 public boolean isLockPatternEnabled() {
Danielle Millett73da5fe2011-09-13 16:20:05 -0400871 final boolean backupEnabled =
872 getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
873 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
874
Jim Millera4edd152012-01-06 18:24:04 -0800875 return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
Danielle Millett73da5fe2011-09-13 16:20:05 -0400876 && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
877 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
Danielle Millett58396982011-09-30 13:55:07 -0400878 (usingBiometricWeak() && backupEnabled));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 }
880
881 /**
Danielle Millett58396982011-09-30 13:55:07 -0400882 * @return Whether biometric weak lock is installed and that the front facing camera exists
Jim Miller6edf2632011-09-05 16:03:14 -0700883 */
Danielle Millett58396982011-09-30 13:55:07 -0400884 public boolean isBiometricWeakInstalled() {
Danielle Millett58396982011-09-30 13:55:07 -0400885 // 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 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700897 if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) {
Danielle Millett58396982011-09-30 13:55:07 -0400898 return false;
899 }
900
901
902 return true;
Jim Miller6edf2632011-09-05 16:03:14 -0700903 }
904
905 /**
Danielle Millett925a7d82012-03-19 18:02:20 -0400906 * 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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 * Set whether the lock pattern is enabled.
929 */
930 public void setLockPatternEnabled(boolean enabled) {
Amith Yamasani156c4352010-03-05 17:10:03 -0800931 setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 }
933
934 /**
935 * @return Whether the visible pattern is enabled.
936 */
937 public boolean isVisiblePatternEnabled() {
Jim Millera4edd152012-01-06 18:24:04 -0800938 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
940
941 /**
942 * Set whether the visible pattern is enabled.
943 */
944 public void setVisiblePatternEnabled(boolean enabled) {
Amith Yamasani156c4352010-03-05 17:10:03 -0800945 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 }
947
948 /**
949 * @return Whether tactile feedback for the pattern is enabled.
950 */
951 public boolean isTactileFeedbackEnabled() {
Jim Millera4edd152012-01-06 18:24:04 -0800952 return getBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 }
954
955 /**
956 * Set whether tactile feedback for the pattern is enabled.
957 */
958 public void setTactileFeedbackEnabled(boolean enabled) {
Amith Yamasani156c4352010-03-05 17:10:03 -0800959 setBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961
962 /**
963 * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
964 * pattern until the deadline has passed.
965 * @return the chosen deadline.
966 */
967 public long setLockoutAttemptDeadline() {
968 final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
969 setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
970 return deadline;
971 }
972
973 /**
974 * @return The elapsed time in millis in the future when the user is allowed to
975 * attempt to enter his/her lock pattern, or 0 if the user is welcome to
976 * enter a pattern.
977 */
978 public long getLockoutAttemptDeadline() {
979 final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
980 final long now = SystemClock.elapsedRealtime();
981 if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
982 return 0L;
983 }
984 return deadline;
985 }
986
987 /**
988 * @return Whether the user is permanently locked out until they verify their
989 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
990 * attempts.
991 */
992 public boolean isPermanentlyLocked() {
Jim Millera4edd152012-01-06 18:24:04 -0800993 return getBoolean(LOCKOUT_PERMANENT_KEY, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 }
995
996 /**
997 * Set the state of whether the device is permanently locked, meaning the user
Karl Rosaen678771b2009-08-21 14:00:26 -0700998 * must authenticate via other means.
999 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 * @param locked Whether the user is permanently locked out until they verify their
1001 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
1002 * attempts.
1003 */
1004 public void setPermanentlyLocked(boolean locked) {
1005 setBoolean(LOCKOUT_PERMANENT_KEY, locked);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 }
1007
John Wang0f7b3f82011-05-31 11:20:55 -07001008 public boolean isEmergencyCallCapable() {
1009 return mContext.getResources().getBoolean(
1010 com.android.internal.R.bool.config_voice_capable);
1011 }
1012
1013 public boolean isPukUnlockScreenEnable() {
1014 return mContext.getResources().getBoolean(
1015 com.android.internal.R.bool.config_enable_puk_unlock_screen);
1016 }
1017
Jim Miller1f56edc2011-11-07 19:00:48 -08001018 public boolean isEmergencyCallEnabledWhileSimLocked() {
1019 return mContext.getResources().getBoolean(
1020 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
1021 }
1022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 /**
1024 * @return A formatted string of the next alarm (for showing on the lock screen),
1025 * or null if there is no next alarm.
1026 */
1027 public String getNextAlarm() {
Amith Yamasani8fd96ec2012-09-21 17:48:49 -07001028 String nextAlarm = Settings.System.getStringForUser(mContentResolver,
1029 Settings.System.NEXT_ALARM_FORMATTED, UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) {
1031 return null;
1032 }
1033 return nextAlarm;
1034 }
1035
Jim Millera4edd152012-01-06 18:24:04 -08001036 private boolean getBoolean(String secureSettingKey, boolean defaultValue) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001037 try {
1038 return getLockSettings().getBoolean(secureSettingKey, defaultValue,
1039 getCurrentOrCallingUserId());
1040 } catch (RemoteException re) {
1041 return defaultValue;
1042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 }
1044
Amith Yamasani156c4352010-03-05 17:10:03 -08001045 private void setBoolean(String secureSettingKey, boolean enabled) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001046 try {
1047 getLockSettings().setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId());
1048 } catch (RemoteException re) {
1049 // What can we do?
1050 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 }
1053
Jim Millerf229e4d2012-09-12 20:32:50 -07001054 public int[] getUserDefinedWidgets() {
1055 int appWidgetId = -1;
Amith Yamasani8fd96ec2012-09-21 17:48:49 -07001056 String appWidgetIdString = Settings.Secure.getStringForUser(
1057 mContentResolver, Settings.Secure.LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID,
1058 UserHandle.USER_CURRENT);
Jim Millerf229e4d2012-09-12 20:32:50 -07001059 if (appWidgetIdString != null) {
1060 appWidgetId = (int) Integer.decode(appWidgetIdString);
1061 }
1062
1063 return new int[] { appWidgetId };
1064 }
1065
Michael Jurka20c41d52012-09-20 19:01:06 -07001066 public int getStatusWidget() {
1067 int appWidgetId = -1;
Amith Yamasani8fd96ec2012-09-21 17:48:49 -07001068 String appWidgetIdString = Settings.Secure.getStringForUser(
1069 mContentResolver, Settings.Secure.LOCK_SCREEN_STATUS_APPWIDGET_ID,
1070 UserHandle.USER_CURRENT);
Michael Jurka20c41d52012-09-20 19:01:06 -07001071 if (appWidgetIdString != null) {
1072 appWidgetId = (int) Integer.decode(appWidgetIdString);
1073 }
1074
1075 return appWidgetId;
1076 }
1077
Amith Yamasani52c489c2012-03-28 11:42:42 -07001078 private long getLong(String secureSettingKey, long defaultValue) {
1079 try {
1080 return getLockSettings().getLong(secureSettingKey, defaultValue,
1081 getCurrentOrCallingUserId());
1082 } catch (RemoteException re) {
1083 return defaultValue;
1084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 }
1086
Amith Yamasani156c4352010-03-05 17:10:03 -08001087 private void setLong(String secureSettingKey, long value) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001088 setLong(secureSettingKey, value, getCurrentOrCallingUserId());
1089 }
1090
1091 private void setLong(String secureSettingKey, long value, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001092 try {
1093 getLockSettings().setLong(secureSettingKey, value, getCurrentOrCallingUserId());
1094 } catch (RemoteException re) {
1095 // What can we do?
1096 Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 }
1099
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001100 private String getString(String secureSettingKey) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001101 return getString(secureSettingKey, getCurrentOrCallingUserId());
1102 }
1103
1104 private String getString(String secureSettingKey, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001105 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001106 return getLockSettings().getString(secureSettingKey, null, userHandle);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001107 } catch (RemoteException re) {
1108 return null;
1109 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001110 }
1111
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001112 private void setString(String secureSettingKey, String value, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001113 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001114 getLockSettings().setString(secureSettingKey, value, userHandle);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001115 } catch (RemoteException re) {
1116 // What can we do?
1117 Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1118 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001119 }
1120
Jim Miller69aa4a92009-12-22 19:03:28 -08001121 public boolean isSecure() {
Jim Millercd709882010-03-25 18:24:02 -07001122 long mode = getKeyguardStoredPasswordQuality();
1123 final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
1124 final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1125 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001126 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1127 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
Jim Millercd709882010-03-25 18:24:02 -07001128 final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
Danielle Millett73da5fe2011-09-13 16:20:05 -04001129 || isPassword && savedPasswordExists();
Jim Miller69aa4a92009-12-22 19:03:28 -08001130 return secure;
1131 }
Jim Miller69ac9882010-02-24 15:35:05 -08001132
1133 /**
John Wang0f7b3f82011-05-31 11:20:55 -07001134 * Sets the emergency button visibility based on isEmergencyCallCapable().
1135 *
1136 * If the emergency button is visible, sets the text on the emergency button
1137 * to indicate what action will be taken.
1138 *
Jim Miller69ac9882010-02-24 15:35:05 -08001139 * If there's currently a call in progress, the button will take them to the call
1140 * @param button the button to update
Jim Miller3f5f83b2011-09-26 15:17:05 -07001141 * @param the phone state:
1142 * {@link TelephonyManager#CALL_STATE_IDLE}
1143 * {@link TelephonyManager#CALL_STATE_RINGING}
1144 * {@link TelephonyManager#CALL_STATE_OFFHOOK}
Jim Miller1f56edc2011-11-07 19:00:48 -08001145 * @param shown indicates whether the given screen wants the emergency button to show at all
Jim Miller109f1fd2012-09-19 20:44:16 -07001146 * @param button
1147 * @param phoneState
1148 * @param shown shown if true; hidden if false
1149 * @param upperCase if true, converts button label string to upper case
Jim Miller69ac9882010-02-24 15:35:05 -08001150 */
Jim Miller109f1fd2012-09-19 20:44:16 -07001151 public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown,
1152 boolean upperCase, boolean showIcon) {
Jim Miller1f56edc2011-11-07 19:00:48 -08001153 if (isEmergencyCallCapable() && shown) {
John Wang0f7b3f82011-05-31 11:20:55 -07001154 button.setVisibility(View.VISIBLE);
1155 } else {
1156 button.setVisibility(View.GONE);
1157 return;
1158 }
1159
Jim Miller69ac9882010-02-24 15:35:05 -08001160 int textId;
Jim Miller3f5f83b2011-09-26 15:17:05 -07001161 if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
Jim Miller69ac9882010-02-24 15:35:05 -08001162 // show "return to call" text and show phone icon
1163 textId = R.string.lockscreen_return_to_call;
Jim Miller109f1fd2012-09-19 20:44:16 -07001164 int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
Jim Miller69ac9882010-02-24 15:35:05 -08001165 button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
1166 } else {
1167 textId = R.string.lockscreen_emergency_call;
Jim Miller109f1fd2012-09-19 20:44:16 -07001168 int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
Jim Miller69ac9882010-02-24 15:35:05 -08001169 button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
1170 }
Jim Miller109f1fd2012-09-19 20:44:16 -07001171 if (upperCase) {
1172 CharSequence original = mContext.getResources().getText(textId);
1173 String upper = original != null ? original.toString().toUpperCase() : null;
1174 button.setText(upper);
1175 } else {
1176 button.setText(textId);
1177 }
1178 }
1179
1180 /**
1181 * @deprecated
1182 * @param button
1183 * @param phoneState
1184 * @param shown
1185 */
1186 public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown) {
1187 updateEmergencyCallButtonState(button, phoneState, shown, false, true);
Jim Miller69ac9882010-02-24 15:35:05 -08001188 }
1189
1190 /**
1191 * Resumes a call in progress. Typically launched from the EmergencyCall button
1192 * on various lockscreens.
1193 *
1194 * @return true if we were able to tell InCallScreen to show.
1195 */
1196 public boolean resumeCall() {
1197 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
1198 try {
1199 if (phone != null && phone.showCallScreen()) {
1200 return true;
1201 }
1202 } catch (RemoteException e) {
1203 // What can we do?
1204 }
1205 return false;
1206 }
Danielle Millett044a0a72011-11-07 15:42:12 -05001207
1208 private void finishBiometricWeak() {
1209 setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
1210
1211 // Launch intent to show final screen, this also
1212 // moves the temporary gallery to the actual gallery
1213 Intent intent = new Intent();
1214 intent.setClassName("com.android.facelock",
1215 "com.android.facelock.SetupEndScreen");
1216 mContext.startActivity(intent);
1217 }
1218
Jim Millera4edd152012-01-06 18:24:04 -08001219 public void setPowerButtonInstantlyLocks(boolean enabled) {
1220 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled);
1221 }
1222
1223 public boolean getPowerButtonInstantlyLocks() {
1224 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true);
1225 }
1226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227}