FileDocCategorySizeDatePackage
LockPatternUtils.javaAPI DocAndroid 1.5 API12810Wed May 06 22:41:56 BST 2009com.android.internal.widget

LockPatternUtils

public class LockPatternUtils extends Object
Utilities for the lock patten and its settings.

Fields Summary
private static final String
TAG
private static final String
LOCK_PATTERN_FILE
public static final int
FAILED_ATTEMPTS_BEFORE_TIMEOUT
The maximum number of incorrect attempts before the user is prevented from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
public static final int
FAILED_ATTEMPTS_BEFORE_RESET
The number of incorrect attempts before which we fall back on an alternative method of verifying the user, and resetting their lock pattern.
public static final long
FAILED_ATTEMPT_TIMEOUT_MS
How long the user is prevented from trying again after entering the wrong pattern too many times.
public static final long
FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS
The interval of the countdown for showing progress of the lockout.
public static final int
MIN_LOCK_PATTERN_SIZE
The minimum number of dots in a valid pattern.
public static final int
MIN_PATTERN_REGISTER_FAIL
The minimum number of dots the user must include in a wrong pattern attempt for it to be counted against the counts that affect {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
private static final String
LOCKOUT_PERMANENT_KEY
private static final String
LOCKOUT_ATTEMPT_DEADLINE
private static final String
PATTERN_EVER_CHOSEN
private final android.content.ContentResolver
mContentResolver
private static String
sLockPatternFilename
Constructors Summary
public LockPatternUtils(android.content.ContentResolver contentResolver)

param
contentResolver Used to look up and save settings.

    
                  
       
        mContentResolver = contentResolver;
        // Initialize the location of gesture lock file
        if (sLockPatternFilename == null) {
            sLockPatternFilename = android.os.Environment.getDataDirectory() 
                    .getAbsolutePath() + LOCK_PATTERN_FILE;
        }
    
Methods Summary
public booleancheckPattern(java.util.List pattern)
Check to see if a pattern matches the saved pattern. If no pattern exists, always returns true.

param
pattern The pattern to check.
return
Whether the pattern matchees the stored one.

        try {
            // Read all the bytes from the file
            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
            final byte[] stored = new byte[(int) raf.length()];
            int got = raf.read(stored, 0, stored.length);
            raf.close();
            if (got <= 0) {
                return true;
            }
            // Compare the hash from the file with the entered pattern's hash
            return Arrays.equals(stored, LockPatternUtils.patternToHash(pattern));
        } catch (FileNotFoundException fnfe) {
            return true;
        } catch (IOException ioe) {
            return true;
        }
    
private booleangetBoolean(java.lang.String systemSettingKey)

        return 1 ==
                android.provider.Settings.System.getInt(
                        mContentResolver,
                        systemSettingKey, 0);
    
public longgetLockoutAttemptDeadline()

return
The elapsed time in millis in the future when the user is allowed to attempt to enter his/her lock pattern, or 0 if the user is welcome to enter a pattern.

        final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
        final long now = SystemClock.elapsedRealtime();
        if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
            return 0L;
        }
        return deadline;
    
private longgetLong(java.lang.String systemSettingKey, long def)

        return android.provider.Settings.System.getLong(mContentResolver, systemSettingKey, def);
    
public java.lang.StringgetNextAlarm()

return
A formatted string of the next alarm (for showing on the lock screen), or null if there is no next alarm.

        String nextAlarm = Settings.System.getString(mContentResolver,
                Settings.System.NEXT_ALARM_FORMATTED);
        if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) {
            return null;
        }
        return nextAlarm;
    
public booleanisLockPatternEnabled()

return
Whether the lock pattern is enabled.

        return getBoolean(Settings.System.LOCK_PATTERN_ENABLED);
    
public booleanisPatternEverChosen()
Return true if the user has ever chosen a pattern. This is true even if the pattern is currently cleared.

return
True if the user has ever chosen a pattern.

        return getBoolean(PATTERN_EVER_CHOSEN);
    
public booleanisPermanentlyLocked()

return
Whether the user is permanently locked out until they verify their credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed attempts.

        return getBoolean(LOCKOUT_PERMANENT_KEY);
    
public booleanisTactileFeedbackEnabled()

return
Whether tactile feedback for the pattern is enabled.

        return getBoolean(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
    
public booleanisVisiblePatternEnabled()

return
Whether the visible pattern is enabled.

        return getBoolean(Settings.System.LOCK_PATTERN_VISIBLE);
    
static byte[]patternToHash(java.util.List pattern)

        if (pattern == null) {
            return null;
        }
        
        final int patternSize = pattern.size();
        byte[] res = new byte[patternSize];
        for (int i = 0; i < patternSize; i++) {
            LockPatternView.Cell cell = pattern.get(i);
            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
        }
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] hash = md.digest(res);
            return hash;
        } catch (NoSuchAlgorithmException nsa) {
            return res;
        }
    
public static java.lang.StringpatternToString(java.util.List pattern)
Serialize a pattern.

param
pattern The pattern.
return
The pattern in string form.

        if (pattern == null) {
            return "";
        }
        final int patternSize = pattern.size();

        byte[] res = new byte[patternSize];
        for (int i = 0; i < patternSize; i++) {
            LockPatternView.Cell cell = pattern.get(i);
            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
        }
        return new String(res);
    
public voidsaveLockPattern(java.util.List pattern)
Save a lock pattern.

param
pattern The new pattern to save.

        // Compute the hash
        final byte[] hash  = LockPatternUtils.patternToHash(pattern);
        try {
            // Write the hash to file
            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw");
            // Truncate the file if pattern is null, to clear the lock
            if (pattern == null) {
                raf.setLength(0);
            } else {
                raf.write(hash, 0, hash.length);
            }
            raf.close();
            setBoolean(PATTERN_EVER_CHOSEN, true);
        } catch (FileNotFoundException fnfe) {
            // Cant do much, unless we want to fail over to using the settings provider
            Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
        } catch (IOException ioe) {
            // Cant do much
            Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
        }
    
public booleansavedPatternExists()
Check to see if the user has stored a lock pattern.

return
Whether a saved pattern exists.

        try {
            // Check if we can read a byte from the file
            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
            byte first = raf.readByte();
            raf.close();
            return true;
        } catch (FileNotFoundException fnfe) {
            return false;
        } catch (IOException ioe) {
            return false;
        }
    
private voidsetBoolean(java.lang.String systemSettingKey, boolean enabled)

        android.provider.Settings.System.putInt(
                        mContentResolver,
                        systemSettingKey,
                        enabled ? 1 : 0);
    
public voidsetLockPatternEnabled(boolean enabled)
Set whether the lock pattern is enabled.

        setBoolean(Settings.System.LOCK_PATTERN_ENABLED, enabled);
    
public longsetLockoutAttemptDeadline()
Set and store the lockout deadline, meaning the user can't attempt his/her unlock pattern until the deadline has passed.

return
the chosen deadline.

        final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
        setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
        return deadline;
    
private voidsetLong(java.lang.String systemSettingKey, long value)

        android.provider.Settings.System.putLong(mContentResolver, systemSettingKey, value);
    
public voidsetPermanentlyLocked(boolean locked)
Set the state of whether the device is permanently locked, meaning the user must authenticate via other means. If false, that means the user has gone out of permanent lock, so the existing (forgotten) lock pattern needs to be cleared.

param
locked Whether the user is permanently locked out until they verify their credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed attempts.

        setBoolean(LOCKOUT_PERMANENT_KEY, locked);

        if (!locked) {
            setLockPatternEnabled(false);
            saveLockPattern(null);
        }
    
public voidsetTactileFeedbackEnabled(boolean enabled)
Set whether tactile feedback for the pattern is enabled.

        setBoolean(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
    
public voidsetVisiblePatternEnabled(boolean enabled)
Set whether the visible pattern is enabled.

        setBoolean(Settings.System.LOCK_PATTERN_VISIBLE, enabled);
    
public static java.util.ListstringToPattern(java.lang.String string)
Deserialize a pattern.

param
string The pattern serialized with {@link #patternToString}
return
The pattern.

        List<LockPatternView.Cell> result = Lists.newArrayList();

        final byte[] bytes = string.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            byte b = bytes[i];
            result.add(LockPatternView.Cell.of(b / 3, b % 3));
        }
        return result;