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

Commit d446b052 authored by Michael Bestas's avatar Michael Bestas Committed by Danny Baumann
Browse files

Forward port CM Screen Security settings (1/2)

* Lockscreen Vibrate
* Slide Lock Delay
* Menu Unlock
* Home Unlock
* Variable size pattern lockscreen
* Toggle dots/error pattern visibility

Forward port from cm-10.2, adjusted for 4.4

Change-Id: Ie1ccaec43ca75474e92f96c60e15d7b75796ac5f
parent e18e0f1d
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -1025,6 +1025,9 @@ public final class Settings {
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_ENABLED);
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_VISIBLE);
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
            MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_SIZE);
            MOVED_TO_SECURE.add(Secure.LOCK_DOTS_VISIBLE);
            MOVED_TO_SECURE.add(Secure.LOCK_SHOW_ERROR_PATH);
            MOVED_TO_SECURE.add(Secure.LOGGING_ID);
            MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_ENABLED);
            MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_LAST_UPDATE);
@@ -3347,6 +3350,18 @@ public final class Settings {
         */
        public static final String PERFORMANCE_PROFILE = "performance_profile";

        /**
         * Whether to unlock the screen with the home key.  The value is boolean (1 or 0).
         * @hide
         */
        public static final String HOME_UNLOCK_SCREEN = "home_unlock_screen";

        /**
         * Whether the lockscreen vibrate should be enabled.
         * @hide
         */
        public static final String LOCKSCREEN_VIBRATE_ENABLED = "lockscreen.vibrate_enabled";

        /**
         * Settings to backup. This is here so that it's in the same place as the settings
         * keys and easy to update.
@@ -3437,6 +3452,7 @@ public final class Settings {
            POWER_MENU_AIRPLANE_ENABLED,
            POWER_MENU_SOUND_ENABLED,
            POWER_MENU_USER_ENABLED,
            LOCKSCREEN_VIBRATE_ENABLED,
            PHONE_BLACKLIST_ENABLED,
            PHONE_BLACKLIST_NOTIFY_ENABLED,
            PHONE_BLACKLIST_PRIVATE_NUMBER_MODE,
@@ -3707,6 +3723,9 @@ public final class Settings {
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_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_DOTS_VISIBLE);
            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_SHOW_ERROR_PATH);

            MOVED_TO_GLOBAL = new HashSet<String>();
            MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
@@ -4399,6 +4418,24 @@ public final class Settings {
        public static final String
                LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";

        /**
         * Determines the width and height of the LockPatternView widget
         * @hide
         */
        public static final String LOCK_PATTERN_SIZE = "lock_pattern_size";

        /**
         * Whether lock pattern will show dots (0 = false, 1 = true)
         * @hide
         */
        public static final String LOCK_DOTS_VISIBLE = "lock_pattern_dotsvisible";

        /**
         * Whether lockscreen error pattern is visible (0 = false, 1 = true)
         * @hide
         */
        public static final String LOCK_SHOW_ERROR_PATH = "lock_pattern_show_error_path";

        /**
         * This preference allows the device to be locked given time after screen goes off,
         * subject to current DeviceAdmin policy limits.
@@ -4450,6 +4487,7 @@ public final class Settings {
         */
        public static final String LOCK_BEFORE_UNLOCK =
            "lock_before_unlock";

        /**
         * The Logging ID (a unique 64-bit value) as a hex string.
         * Used as a pseudonymous identifier for logging.
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ interface ILockSettings {
    boolean getBoolean(in String key, in boolean defaultValue, in int userId);
    long getLong(in String key, in long defaultValue, in int userId);
    String getString(in String key, in String defaultValue, in int userId);
    byte getLockPatternSize(int userId);
    void setLockPattern(in String pattern, int userId);
    boolean checkPattern(in String pattern, int userId);
    void setLockPassword(in String password, int userId);
+48 −6
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ public class LockPatternUtils {
     */
    public static final int MIN_LOCK_PATTERN_SIZE = 4;

    /**
     * The default size of the pattern lockscreen. Ex: 3x3
     */
    public static final byte PATTERN_SIZE_DEFAULT = 3;

    /**
     * The minimum number of dots the user must include in a wrong pattern
     * attempt for it to be counted against the counts that affect
@@ -752,13 +757,16 @@ public class LockPatternUtils {
     * @param string The pattern serialized with {@link #patternToString}
     * @return The pattern.
     */
    public static List<LockPatternView.Cell> stringToPattern(String string) {
    public List<LockPatternView.Cell> stringToPattern(String string) {
        List<LockPatternView.Cell> result = Lists.newArrayList();

        final byte size = getLockPatternSize();
        LockPatternView.Cell.updateSize(size);

        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 / size, b % size, size));
        }
        return result;
    }
@@ -768,7 +776,7 @@ public class LockPatternUtils {
     * @param pattern The pattern.
     * @return The pattern in string form.
     */
    public static String patternToString(List<LockPatternView.Cell> pattern) {
    public String patternToString(List<LockPatternView.Cell> pattern) {
        if (pattern == null) {
            return "";
        }
@@ -777,7 +785,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() * getLockPatternSize() + cell.getColumn());
        }
        return new String(res);
    }
@@ -789,7 +797,7 @@ public class LockPatternUtils {
     * @param pattern the gesture pattern.
     * @return the hash of the pattern in a byte array.
     */
    public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
    public byte[] patternToHash(List<LockPatternView.Cell> pattern) {
        if (pattern == null) {
            return null;
        }
@@ -798,7 +806,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() * getLockPatternSize() + cell.getColumn());
        }
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
@@ -966,6 +974,40 @@ public class LockPatternUtils {
                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
    }

    /**
     * @return the pattern lockscreen size
     */
    public byte getLockPatternSize() {
        try {
            return getLockSettings().getLockPatternSize(getCurrentOrCallingUserId());
        } catch (RemoteException re) {
            return PATTERN_SIZE_DEFAULT;
        }
    }

    /**
     * Set the pattern lockscreen size
     */
    public void setLockPatternSize(long size) {
        setLong(Settings.Secure.LOCK_PATTERN_SIZE, size);
    }

    public void setVisibleDotsEnabled(boolean enabled) {
        setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled);
    }

    public boolean isVisibleDotsEnabled() {
        return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true);
    }

    public void setShowErrorPath(boolean enabled) {
        setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled);
    }

    public boolean isShowErrorPath() {
        return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true);
    }

    /**
     * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
     * pattern until the deadline has passed.
+138 −54
Original line number Diff line number Diff line
@@ -38,13 +38,14 @@ import android.view.View;
import android.view.accessibility.AccessibilityManager;

import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;

import java.util.ArrayList;
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 regions of the screen.
 *
 * Is also capable of displaying a static pattern in "in progress", "wrong" or
 * "correct" states.
@@ -68,6 +69,8 @@ public class LockPatternView extends View {
     */
    private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;

    private byte mPatternSize = LockPatternUtils.PATTERN_SIZE_DEFAULT;

    /**
     * This can be used to avoid updating the display for very small motions or noisy panels.
     * It didn't seem to have much impact on the devices tested, so currently set to 0.
@@ -75,7 +78,7 @@ public class LockPatternView extends View {
    private static final float DRAG_THRESHHOLD = 0.0f;

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

    /**
     * Lookup table for the circles of the pattern we are currently drawing.
@@ -83,7 +86,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[mPatternSize][mPatternSize];

    /**
     * the in progress point:
@@ -100,6 +103,8 @@ public class LockPatternView extends View {
    private boolean mInStealthMode = false;
    private boolean mEnableHapticFeedback = true;
    private boolean mPatternInProgress = false;
    private boolean mVisibleDots = true;
    private boolean mShowErrorPath = true;

    private float mDiameterFactor = 0.10f; // TODO: move to attrs
    private final int mStrokeAlpha = 128;
@@ -128,29 +133,27 @@ public class LockPatternView extends View {
    private final Matrix mArrowMatrix = new Matrix();
    private final Matrix mCircleMatrix = new Matrix();

    private LockPatternUtils mLockPatternUtils;

    /**
     * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
     * Represents a cell in the 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
        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(LockPatternUtils.PATTERN_SIZE_DEFAULT);
        }

        /**
         * @param row The row of the cell.
         * @param column The column of the cell.
         */
        private Cell(int row, int column) {
            checkRange(row, column);
        private Cell(int row, int column, byte size) {
            checkRange(row, column, size);
            this.row = row;
            this.column = column;
        }
@@ -167,17 +170,26 @@ public class LockPatternView extends View {
         * @param row The row of the cell.
         * @param column The column of the cell.
         */
        public static synchronized Cell of(int row, int column) {
            checkRange(row, column);
        public static synchronized Cell of(int row, int column, byte size) {
            checkRange(row, column, size);
            return sCells[row][column];
        }

        private static void checkRange(int row, int column) {
            if (row < 0 || row > 2) {
                throw new IllegalArgumentException("row must be in range 0-2");
        public static void updateSize(byte size) {
            sCells = new Cell[size][size];
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    sCells[i][j] = new Cell(i, j, size);
                }
            if (column < 0 || column > 2) {
                throw new IllegalArgumentException("column must be in range 0-2");
            }
        }

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

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

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

    /**
     * Set whether the view is in stealth mode.  If true, there will be no
     * visible feedback as the user enters the pattern.
@@ -315,6 +334,22 @@ public class LockPatternView extends View {
        mInStealthMode = inStealthMode;
    }

    public void setVisibleDots(boolean visibleDots) {
        mVisibleDots = visibleDots;
    }

    public boolean isVisibleDots() {
        return mVisibleDots;
    }

    public void setShowErrorPath(boolean showErrorPath) {
        mShowErrorPath = showErrorPath;
    }

    public boolean isShowErrorPath() {
        return mShowErrorPath;
    }

    /**
     * Set whether the view will use tactile feedback.  If true, there will be
     * tactile feedback as the user enters the pattern.
@@ -325,6 +360,26 @@ public class LockPatternView extends View {
        mEnableHapticFeedback = tactileFeedbackEnabled;
    }

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

    /**
     * Set the LockPatternUtil instance used to encode a pattern to a string
     * @param utils The instance.
     */
    public void setLockPatternUtils(LockPatternUtils utils) {
        mLockPatternUtils = utils;
    }

    /**
     * Set the call back for pattern detection.
     * @param onPatternListener The call back.
@@ -422,8 +477,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 < mPatternSize; i++) {
            for (int j = 0; j < mPatternSize; j++) {
                mPatternDrawLookup[i][j] = false;
            }
        }
@@ -447,10 +502,10 @@ 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) mPatternSize;

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

    private int resolveMeasured(int measureSpec, int desired)
@@ -473,14 +528,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 side-by-side target bitmaps
        return mPatternSize * 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 side-by-side target bitmaps
        return mPatternSize * mBitmapWidth;
    }

    @Override
@@ -517,7 +572,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);
@@ -527,21 +581,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, mPatternSize);
                        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,
@@ -574,7 +626,7 @@ public class LockPatternView extends View {
        if (mPatternDrawLookup[rowHit][columnHit]) {
            return null;
        }
        return Cell.of(rowHit, columnHit);
        return Cell.of(rowHit, columnHit, mPatternSize);
    }

    /**
@@ -588,7 +640,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 < mPatternSize; i++) {

            final float hitTop = offset + squareHeight * i;
            if (y >= hitTop && y <= hitTop + hitSize) {
@@ -608,7 +660,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 < mPatternSize; i++) {

            final float hitLeft = offset + squareWidth * i;
            if (x >= hitLeft && x <= hitLeft + hitSize) {
@@ -857,10 +909,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 < mPatternSize; 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 < mPatternSize; j++) {
                float leftX = paddingLeft + j * squareWidth;
                drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
            }
@@ -870,7 +922,8 @@ public class LockPatternView extends View {
        // only the last segment of the path should be computed here
        // draw the path of the pattern (unless the user is in progress, and
        // we are in stealth mode)
        final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
        final boolean drawPath = ((!mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
                || (mPatternDisplayMode == DisplayMode.Wrong && mShowErrorPath));

        // draw the arrows associated with the path (unless the user is in progress, and
        // we are in stealth mode)
@@ -973,8 +1026,11 @@ public class LockPatternView extends View {
    private void drawCircle(Canvas canvas, int leftX, int topY, boolean partOfPattern) {
        Bitmap outerCircle;
        Bitmap innerCircle;

        if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)) {
        if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
                || (mPatternDisplayMode == DisplayMode.Wrong && !mShowErrorPath)) {
            if (!mVisibleDots) {
                return;
            }
            // unselected circle
            outerCircle = mBitmapCircleDefault;
            innerCircle = mBitmapBtnDefault;
@@ -1021,9 +1077,9 @@ public class LockPatternView extends View {
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        return new SavedState(superState,
                LockPatternUtils.patternToString(mPattern),
                mPatternDisplayMode.ordinal(),
                mInputEnabled, mInStealthMode, mEnableHapticFeedback);
                mLockPatternUtils.patternToString(mPattern),
                mPatternDisplayMode.ordinal(), mPatternSize,
                mInputEnabled, mInStealthMode, mEnableHapticFeedback, mVisibleDots, mShowErrorPath);
    }

    @Override
@@ -1032,11 +1088,14 @@ public class LockPatternView extends View {
        super.onRestoreInstanceState(ss.getSuperState());
        setPattern(
                DisplayMode.Correct,
                LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
                mLockPatternUtils.stringToPattern(ss.getSerializedPattern()));
        mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
        mPatternSize = ss.getPatternSize();
        mInputEnabled = ss.isInputEnabled();
        mInStealthMode = ss.isInStealthMode();
        mEnableHapticFeedback = ss.isTactileFeedbackEnabled();
        mVisibleDots = ss.isVisibleDots();
        mShowErrorPath = ss.isShowErrorPath();
    }

    /**
@@ -1046,21 +1105,28 @@ public class LockPatternView extends View {

        private final String mSerializedPattern;
        private final int mDisplayMode;
        private final byte mPatternSize;
        private final boolean mInputEnabled;
        private final boolean mInStealthMode;
        private final boolean mTactileFeedbackEnabled;
        private final boolean mVisibleDots;
        private final boolean mShowErrorPath;

        /**
         * Constructor called from {@link LockPatternView#onSaveInstanceState()}
         */
        private SavedState(Parcelable superState, String serializedPattern, int displayMode,
                boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
                byte patternSize, boolean inputEnabled, boolean inStealthMode,
                boolean tactileFeedbackEnabled, boolean visibleDots, boolean showErrorPath) {
            super(superState);
            mSerializedPattern = serializedPattern;
            mDisplayMode = displayMode;
            mPatternSize = patternSize;
            mInputEnabled = inputEnabled;
            mInStealthMode = inStealthMode;
            mTactileFeedbackEnabled = tactileFeedbackEnabled;
            mVisibleDots = visibleDots;
            mShowErrorPath = showErrorPath;
        }

        /**
@@ -1070,9 +1136,12 @@ public class LockPatternView extends View {
            super(in);
            mSerializedPattern = in.readString();
            mDisplayMode = in.readInt();
            mPatternSize = (byte) in.readByte();
            mInputEnabled = (Boolean) in.readValue(null);
            mInStealthMode = (Boolean) in.readValue(null);
            mTactileFeedbackEnabled = (Boolean) in.readValue(null);
            mVisibleDots = (Boolean) in.readValue(null);
            mShowErrorPath = (Boolean) in.readValue(null);
        }

        public String getSerializedPattern() {
@@ -1083,6 +1152,10 @@ public class LockPatternView extends View {
            return mDisplayMode;
        }

        public byte getPatternSize() {
            return mPatternSize;
        }

        public boolean isInputEnabled() {
            return mInputEnabled;
        }
@@ -1095,14 +1168,25 @@ public class LockPatternView extends View {
            return mTactileFeedbackEnabled;
        }

        public boolean isVisibleDots() {
            return mVisibleDots;
        }

        public boolean isShowErrorPath() {
            return mShowErrorPath;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeString(mSerializedPattern);
            dest.writeInt(mDisplayMode);
            dest.writeByte(mPatternSize);
            dest.writeValue(mInputEnabled);
            dest.writeValue(mInStealthMode);
            dest.writeValue(mTactileFeedbackEnabled);
            dest.writeValue(mVisibleDots);
            dest.writeValue(mShowErrorPath);
        }

        public static final Parcelable.Creator<SavedState> CREATOR =
+18 −1
Original line number Diff line number Diff line
@@ -1703,7 +1703,15 @@ public class KeyguardHostView extends KeyguardViewBase {
        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
        return !configDisabled || isTestHarness || fileOverride;
        final boolean menuOverride = Settings.System.getInt(getContext().getContentResolver(),
                Settings.System.MENU_UNLOCK_SCREEN, 0) == 1;
        return !configDisabled || isTestHarness || fileOverride || menuOverride;
    }

    private boolean shouldEnableHomeKey() {
        final boolean homeOverride = Settings.System.getInt(getContext().getContentResolver(),
                Settings.System.HOME_UNLOCK_SCREEN, 0) == 1;
        return homeOverride;
    }

    public void goToWidget(int appWidgetId) {
@@ -1720,6 +1728,15 @@ public class KeyguardHostView extends KeyguardViewBase {
        return false;
    }

    public boolean handleHomeKey() {
        // The following enables the HOME key to work for testing automation
        if (shouldEnableHomeKey()) {
            showNextSecurityScreenOrFinish(false);
            return true;
        }
        return false;
    }

    public boolean handleBackKey() {
        if (mCurrentSecuritySelection == SecurityMode.Account) {
            // go back to primary screen and re-disable back
Loading