Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f4e7b76 authored by Rowan Decker's avatar Rowan Decker Committed by Gerrit Code Review
Browse files

Framwork: Add support for variable size pattern lockscreen (Part 1/2)

Changes LockPatternView to use PATTERN_SIZE instead of the hardcoded value '3'.
Adds methods to set and get PATTERN_SIZE via LockPatternUtils and device settings.

With this patch the pattern lockscreen can go from 3x3 to any sane size such as 6x6.
LockPatternView can be taken by itself if settings are not desired, for an easy way to change the hardcoded size.

Patch Set 3: Rebased,
should fix cherry-pick after the "widgets before unlock" commit.

Patch Set 4+5: Fix whitespace
Patch Set 6: Missed one Gremlin. (Fixed for real)

Patch Set 7: Rebased

Patch Set 8: Added missing hide statements

Change-Id: Ibc0d5bfcee9673b1bf049bd69be80d2312602a47
parent 0f1f6f19
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -805,6 +805,7 @@ public final class Settings {
            MOVED_TO_SECURE.add(Secure.LOCK_SHOW_ERROR_PATH);
            MOVED_TO_SECURE.add(Secure.LOCK_DOTS_VISIBLE);
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_SIZE);
            MOVED_TO_SECURE.add(Secure.LOGGING_ID);
            MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_ENABLED);
            MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_LAST_UPDATE);
@@ -1358,6 +1359,14 @@ public final class Settings {
        public static final String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED =
            "lock_pattern_tactile_feedback_enabled";

         /**
         * @deprecated Use {@link android.provider.Settings.Secure#LOCK_PATTERN_SIZE}
         * instead
         * @hide
         */
        @Deprecated
        public static final String LOCK_PATTERN_SIZE =
            "lock_pattern_size";

        /**
         * A formatted string of the next alarm that is set, or the empty string
@@ -3113,6 +3122,7 @@ public final class Settings {
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_SHOW_ERROR_PATH);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_DOTS_VISIBLE);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_SIZE);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_BEFORE_UNLOCK);
        }

@@ -3597,6 +3607,13 @@ public final class Settings {
         */
        public static final String LOCK_SHOW_ERROR_PATH = "lock_pattern_show_error_path";

        /**
         * Size of pattern lockscreen
         * @hide
         */
        public static final String LOCK_PATTERN_SIZE = "lock_pattern_size";


        /**
         * This preference allows the device to be locked given time after screen goes off,
         * subject to current DeviceAdmin policy limits.
+2 −0
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@ package com.android.internal.widget;
interface ILockSettings {
    void setBoolean(in String key, in boolean value, in int userId);
    void setLong(in String key, in long value, in int userId);
    void setInteger(in String key, in int value, in int userId);
    void setString(in String key, in String value, in int userId);
    boolean getBoolean(in String key, in boolean defaultValue, in int userId);
    long getLong(in String key, in long defaultValue, in int userId);
    int getInteger(in String key, in int defaultValue, in int userId);
    String getString(in String key, in String defaultValue, in int userId);
    void setLockPattern(in byte[] hash, int userId);
    boolean checkPattern(in byte[] hash, int userId);
+47 −3
Original line number Diff line number Diff line
@@ -144,6 +144,8 @@ public class LockPatternUtils {
    private ILockSettings mLockSettingsService;
    private int mCurrentUserId = 0;

    private static int PATTERN_SIZE = 3;

    public DevicePolicyManager getDevicePolicyManager() {
        if (mDevicePolicyManager == null) {
            mDevicePolicyManager =
@@ -704,7 +706,7 @@ public class LockPatternUtils {
        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));
            result.add(LockPatternView.Cell.of(b / PATTERN_SIZE, b % PATTERN_SIZE));
        }
        return result;
    }
@@ -723,7 +725,7 @@ public class LockPatternUtils {
        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());
            res[i] = (byte) (cell.getRow() * PATTERN_SIZE + cell.getColumn());
        }
        return new String(res);
    }
@@ -744,7 +746,7 @@ public class LockPatternUtils {
        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());
            res[i] = (byte) (cell.getRow() * PATTERN_SIZE + cell.getColumn());
        }
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
@@ -934,6 +936,30 @@ public class LockPatternUtils {
        return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true);
    }

    /**
     * @return the pattern lockscreen size
     */
    public int getLockPatternSize() {
        return getInteger(Settings.Secure.LOCK_PATTERN_SIZE, 3);
    }

    /**
     * Set the pattern lockscreen size
     */
    public void setLockPatternSize(int size) {
        setInteger(Settings.Secure.LOCK_PATTERN_SIZE, size);
        PATTERN_SIZE = size;
    }

    /**
     * Update PATTERN_SIZE for this LockPatternUtils instance
     * This must be called before patternToHash, patternToString, etc
     * will work correctly with a non-standard size
     */
    public void updateLockPatternSize() {
        PATTERN_SIZE = getLockPatternSize();
    }

    /**
     * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
     * pattern until the deadline has passed.
@@ -1204,6 +1230,24 @@ public class LockPatternUtils {
        }
    }

    private int getInteger(String secureSettingKey, int defaultValue) {
        try {
            return getLockSettings().getInteger(secureSettingKey, defaultValue,
                    getCurrentOrCallingUserId());
        } catch (RemoteException re) {
            return defaultValue;
        }
    }

    private void setInteger(String secureSettingKey, int value) {
        try {
            getLockSettings().setInteger(secureSettingKey, value, getCurrentOrCallingUserId());
        } catch (RemoteException re) {
            // What can we do?
            Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
        }
    }

    private String getString(String secureSettingKey) {
        try {
            return getLockSettings().getString(secureSettingKey, null,
+64 −41
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import java.util.List;

/**
 * Displays and detects the user's unlock attempt, which is a drag of a finger
 * across 9 regions of the screen.
 * across PATTERN_SIZE regions of the screen.
 *
 * Is also capable of displaying a static pattern in "in progress", "wrong" or
 * "correct" states.
@@ -77,7 +77,7 @@ public class LockPatternView extends View {
    private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;

    private OnPatternListener mOnPatternListener;
    private ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
    private ArrayList<Cell> mPattern = new ArrayList<Cell>(PATTERN_SIZE*PATTERN_SIZE);

    /**
     * Lookup table for the circles of the pattern we are currently drawing.
@@ -85,7 +85,7 @@ public class LockPatternView extends View {
     * in which case we use this to hold the cells we are drawing for the in
     * progress animation.
     */
    private boolean[][] mPatternDrawLookup = new boolean[3][3];
    private boolean[][] mPatternDrawLookup = new boolean[PATTERN_SIZE][PATTERN_SIZE];

    /**
     * the in progress point:
@@ -134,22 +134,19 @@ public class LockPatternView extends View {
    private final Matrix mArrowMatrix = new Matrix();
    private final Matrix mCircleMatrix = new Matrix();

    private static int PATTERN_SIZE = 3;

    /**
     * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
     * Represents a cell in the PATTERN_SIZE X PATTERN_SIZE matrix of the unlock pattern view.
     */
    public static class Cell {
        int row;
        int column;

        // keep # objects limited to 9
        static Cell[][] sCells = new Cell[3][3];
        // keep # objects limited to PATTERN_SIZE
        static Cell[][] sCells;
        static {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    sCells[i][j] = new Cell(i, j);
                }
            }
            updateSize();
        }

        /**
@@ -179,12 +176,21 @@ public class LockPatternView extends View {
            return sCells[row][column];
        }

        public static void updateSize() {
           sCells = new Cell[PATTERN_SIZE][PATTERN_SIZE];
           for (int i = 0; i < PATTERN_SIZE; i++) {
                for (int j = 0; j < PATTERN_SIZE; j++) {
                    sCells[i][j] = new Cell(i, j);
                }
            }
        }

        private static void checkRange(int row, int column) {
            if (row < 0 || row > 2) {
                throw new IllegalArgumentException("row must be in range 0-2");
            if (row < 0 || row > PATTERN_SIZE-1) {
                throw new IllegalArgumentException("row must be in range 0-" + (PATTERN_SIZE-1));
            }
            if (column < 0 || column > 2) {
                throw new IllegalArgumentException("column must be in range 0-2");
            if (column < 0 || column > PATTERN_SIZE-1) {
                throw new IllegalArgumentException("column must be in range 0-" + (PATTERN_SIZE-1));
            }
        }

@@ -320,6 +326,13 @@ public class LockPatternView extends View {
        return mEnableHapticFeedback;
    }

    /**
     * @return the current pattern lockscreen size
     */
    public int getLockPatternSize() {
        return PATTERN_SIZE;
    }

    /**
     * Set whether the view is in stealth mode.  If true, there will be no
     * visible feedback as the user enters the pattern.
@@ -356,6 +369,18 @@ public class LockPatternView extends View {
        mEnableHapticFeedback = tactileFeedbackEnabled;
    }

    /**
     * Set the PATTERN_SIZE size of the lockscreen
     *
     * @param size
     */
    public void setLockPatternSize(int size) {
        PATTERN_SIZE = size;
        mPattern = new ArrayList<Cell>(PATTERN_SIZE*PATTERN_SIZE);
        mPatternDrawLookup = new boolean[PATTERN_SIZE][PATTERN_SIZE];
        Cell.updateSize();
    }

    /**
     * Set the call back for pattern detection.
     * @param onPatternListener The call back.
@@ -453,8 +478,8 @@ public class LockPatternView extends View {
     * Clear the pattern lookup table.
     */
    private void clearPatternDrawLookup() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
        for (int i = 0; i < PATTERN_SIZE; i++) {
            for (int j = 0; j < PATTERN_SIZE; j++) {
                mPatternDrawLookup[i][j] = false;
            }
        }
@@ -478,13 +503,13 @@ public class LockPatternView extends View {
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        final int width = w - mPaddingLeft - mPaddingRight;
        mSquareWidth = width / 3.0f;
        mSquareWidth = width / (float)PATTERN_SIZE;

        final int height = h - mPaddingTop - mPaddingBottom;
        mSquareHeight = height / 3.0f;
        mSquareHeight = height / (float)PATTERN_SIZE;

        // Try to set a message size relative to square size
        mMsgPaint.setTextSize(mSquareHeight / 6);
        mMsgPaint.setTextSize(mSquareHeight / (PATTERN_SIZE*2));
    }

    private int resolveMeasured(int measureSpec, int desired)
@@ -507,14 +532,14 @@ public class LockPatternView extends View {

    @Override
    protected int getSuggestedMinimumWidth() {
        // View should be large enough to contain 3 side-by-side target bitmaps
        return 3 * mBitmapWidth;
        // View should be large enough to contain PATTERN_SIZE side-by-side target bitmaps
        return PATTERN_SIZE * mBitmapWidth;
    }

    @Override
    protected int getSuggestedMinimumHeight() {
        // View should be large enough to contain 3 side-by-side target bitmaps
        return 3 * mBitmapWidth;
        // View should be large enough to contain PATTERN_SIZE side-by-side target bitmaps
        return PATTERN_SIZE * mBitmapWidth;
    }

    @Override
@@ -551,7 +576,6 @@ public class LockPatternView extends View {
        if (cell != null) {

            // check for gaps in existing pattern
            Cell fillInGapCell = null;
            final ArrayList<Cell> pattern = mPattern;
            if (!pattern.isEmpty()) {
                final Cell lastCell = pattern.get(pattern.size() - 1);
@@ -561,21 +585,19 @@ public class LockPatternView extends View {
                int fillInRow = lastCell.row;
                int fillInColumn = lastCell.column;

                if (Math.abs(dRow) == 2 && Math.abs(dColumn) != 1) {
                    fillInRow = lastCell.row + ((dRow > 0) ? 1 : -1);
                if (!( (dRow!=0) && (dColumn!=0) && (Math.abs(dRow)!=Math.abs(dColumn)) )) {
                    while (true) {
                        fillInRow += Integer.signum(dRow);
                        fillInColumn += Integer.signum(dColumn);
                        if ( (fillInRow==cell.row) && (fillInColumn==cell.column) ) break;
                        Cell fillInGapCell = Cell.of(fillInRow, fillInColumn);
                        if ( !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
                            addCellToPattern(fillInGapCell);
                          }

                if (Math.abs(dColumn) == 2 && Math.abs(dRow) != 1) {
                    fillInColumn = lastCell.column + ((dColumn > 0) ? 1 : -1);
                       }

                fillInGapCell = Cell.of(fillInRow, fillInColumn);
                }

            if (fillInGapCell != null &&
                    !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
                addCellToPattern(fillInGapCell);
            }

            addCellToPattern(cell);
            if (mEnableHapticFeedback) {
                performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
@@ -591,6 +613,7 @@ public class LockPatternView extends View {
        mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
        mPattern.add(newCell);
        notifyCellAdded();
        Log.v("SMASHER816", "("+newCell.column+", "+newCell.row+")");
    }

    // helper method to find which cell a point maps to
@@ -622,7 +645,7 @@ public class LockPatternView extends View {
        float hitSize = squareHeight * mHitFactor;

        float offset = mPaddingTop + (squareHeight - hitSize) / 2f;
        for (int i = 0; i < 3; i++) {
        for (int i = 0; i < PATTERN_SIZE; i++) {

            final float hitTop = offset + squareHeight * i;
            if (y >= hitTop && y <= hitTop + hitSize) {
@@ -642,7 +665,7 @@ public class LockPatternView extends View {
        float hitSize = squareWidth * mHitFactor;

        float offset = mPaddingLeft + (squareWidth - hitSize) / 2f;
        for (int i = 0; i < 3; i++) {
        for (int i = 0; i < PATTERN_SIZE; i++) {

            final float hitLeft = offset + squareWidth * i;
            if (x >= hitLeft && x <= hitLeft + hitSize) {
@@ -954,10 +977,10 @@ public class LockPatternView extends View {
        final int paddingTop = mPaddingTop;
        final int paddingLeft = mPaddingLeft;

        for (int i = 0; i < 3; i++) {
        for (int i = 0; i < PATTERN_SIZE; i++) {
            float topY = paddingTop + i * squareHeight;
            //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
            for (int j = 0; j < 3; j++) {
            for (int j = 0; j < PATTERN_SIZE; j++) {
                float leftX = paddingLeft + j * squareWidth;
                drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
            }
+15 −0
Original line number Diff line number Diff line
@@ -133,6 +133,13 @@ public class LockSettingsService extends ILockSettings.Stub {
        writeToDb(key, Long.toString(value), userId);
    }

    @Override
    public void setInteger(String key, int value, int userId) throws RemoteException {
        checkWritePermission(userId);

        writeToDb(key, Integer.toString(value), userId);
    }

    @Override
    public void setString(String key, String value, int userId) throws RemoteException {
        checkWritePermission(userId);
@@ -157,6 +164,14 @@ public class LockSettingsService extends ILockSettings.Stub {
        return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
    }

    @Override
    public int getInteger(String key, int defaultValue, int userId) throws RemoteException {
        //checkReadPermission(userId);

        String value = readFromDb(key, null, userId);
        return TextUtils.isEmpty(value) ? defaultValue : Integer.parseInt(value);
    }

    @Override
    public String getString(String key, String defaultValue, int userId) throws RemoteException {
        //checkReadPermission(userId);
Loading