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

Commit d21af708 authored by ctso's avatar ctso
Browse files

Merge branch 'eclair' of git://github.com/cyanogen/android_frameworks_base into eclair

parents 5a2910ae c81921b8
Loading
Loading
Loading
Loading
+74 −169
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ import java.util.List;
 * Is also capable of displaying a static pattern in "in progress", "wrong" or
 * "correct" states.
 */
public class LockPatternView extends View {
public class DragLock extends View implements LockPattern {
    // Vibrator pattern for creating a tactile bump
    private static final long[] DEFAULT_VIBE_PATTERN = {0, 1, 40, 41};

@@ -69,7 +69,7 @@ public class LockPatternView extends View {
     */
    private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;

    private OnPatternListener mOnPatternListener;
    private EventListener mEventListener;
    private ArrayList<Cell> mPattern = new ArrayList<Cell>(9);

    /**
@@ -90,11 +90,10 @@ public class LockPatternView extends View {

    private long mAnimatingPeriodStart;

    private DisplayMode mPatternDisplayMode = DisplayMode.Correct;
    private State mState = State.Record;
    private boolean mInputEnabled = true;
    private boolean mInStealthMode = false;
    private boolean mTactileFeedbackEnabled = true;
    private boolean mPatternInProgress = false;

    private float mDiameterFactor = 0.5f;
    private float mHitFactor = 0.6f;
@@ -122,118 +121,11 @@ public class LockPatternView extends View {

    private long[] mVibePattern;

    /**
     * Represents a cell in the 3 X 3 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];
        static {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    sCells[i][j] = new Cell(i, j);
                }
            }
        }

        /**
         * @param row The row of the cell.
         * @param column The column of the cell.
         */
        private Cell(int row, int column) {
            checkRange(row, column);
            this.row = row;
            this.column = column;
        }

        public int getRow() {
            return row;
        }

        public int getColumn() {
            return column;
        }

        /**
         * @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);
            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");
            }
            if (column < 0 || column > 2) {
                throw new IllegalArgumentException("column must be in range 0-2");
            }
        }

        public String toString() {
            return "(row=" + row + ",clmn=" + column + ")";
        }
    }

    /**
     * How to display the current pattern.
     */
    public enum DisplayMode {

        /**
         * The pattern drawn is correct (i.e draw it in a friendly color)
         */
        Correct,

        /**
         * Animate the pattern (for demo, and help).
         */
        Animate,

        /**
         * The pattern is wrong (i.e draw a foreboding color)
         */
        Wrong
    }

    /**
     * The call back interface for detecting patterns entered by the user.
     */
    public static interface OnPatternListener {

        /**
         * A new pattern has begun.
         */
        void onPatternStart();

        /**
         * The pattern was cleared.
         */
        void onPatternCleared();

        /**
         * The user extended the pattern currently being drawn by one cell.
         * @param pattern The pattern with newly added cell.
         */
        void onPatternCellAdded(List<Cell> pattern);

        /**
         * A pattern was detected from the user.
         * @param pattern The pattern.
         */
        void onPatternDetected(List<Cell> pattern);
    }

    public LockPatternView(Context context) {
    public DragLock(Context context) {
        this(context, null);
    }

    public LockPatternView(Context context, AttributeSet attrs) {
    public DragLock(Context context, AttributeSet attrs) {
        super(context, attrs);
        vibe = new Vibrator();

@@ -283,6 +175,10 @@ public class LockPatternView extends View {
        return tmpPattern;
    }

    public View getView() {
        return this;
    }

    private Bitmap getBitmapFor(int resId) {
        return BitmapFactory.decodeResource(getContext().getResources(), resId);
    }
@@ -323,20 +219,19 @@ public class LockPatternView extends View {

    /**
     * Set the call back for pattern detection.
     * @param onPatternListener The call back.
     * @param eventeListener The call back.
     */
    public void setOnPatternListener(
            OnPatternListener onPatternListener) {
        mOnPatternListener = onPatternListener;
    public void setEventListener(EventListener eventeListener) {
        mEventListener = eventeListener;
    }

    /**
     * Set the pattern explicitely (rather than waiting for the user to input
     * a pattern).
     * @param displayMode How to display the pattern.
     * @param state How to display the pattern.
     * @param pattern The pattern.
     */
    public void setPattern(DisplayMode displayMode, List<Cell> pattern) {
    public void setPattern(State state, List<Cell> pattern) {
        mPattern.clear();
        mPattern.addAll(pattern);
        clearPatternDrawLookup();
@@ -344,7 +239,7 @@ public class LockPatternView extends View {
            mPatternDrawLookup[cell.getRow()][cell.getColumn()] = true;
        }

        setDisplayMode(displayMode);
        setState(state);
    }

    /**
@@ -353,9 +248,9 @@ public class LockPatternView extends View {
     * in progress result to correct or wrong.
     * @param displayMode The display mode.
     */
    public void setDisplayMode(DisplayMode displayMode) {
        mPatternDisplayMode = displayMode;
        if (displayMode == DisplayMode.Animate) {
    public void setState(State state) {
        mState = state;
        if (state == State.Replay) {
            if (mPattern.size() == 0) {
                throw new IllegalStateException("you must have a pattern to "
                        + "animate if you want to set the display mode to animate");
@@ -366,6 +261,9 @@ public class LockPatternView extends View {
            mInProgressY = getCenterYForRow(first.getRow());
            clearPatternDrawLookup();
        }
        else if (state == State.Record) {
            resetPattern();
        }
        invalidate();
    }

@@ -382,7 +280,7 @@ public class LockPatternView extends View {
    private void resetPattern() {
        mPattern.clear();
        clearPatternDrawLookup();
        mPatternDisplayMode = DisplayMode.Correct;
        mState = State.Record;
        invalidate();
    }

@@ -412,6 +310,14 @@ public class LockPatternView extends View {
        mInputEnabled = true;
    }

    public int getCorrectDelay() {
        return 0;
    }

    public int getIncorrectDelay() {
        return 1500;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        final int width = w - mPaddingLeft - mPaddingRight;
@@ -478,8 +384,9 @@ public class LockPatternView extends View {
    private void addCellToPattern(Cell newCell) {
        mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
        mPattern.add(newCell);
        if (mOnPatternListener != null) {
            mOnPatternListener.onPatternCellAdded(mPattern);
        if (mEventListener != null) {
            mEventListener.onUserInteraction();
            //mEventListener.onPatternCellAdded(mPattern);
        }
    }

@@ -548,6 +455,10 @@ public class LockPatternView extends View {
            return false;
        }

        if (mState != State.Record) {
            return false;
        }

        final float x = motionEvent.getX();
        final float y = motionEvent.getY();
        Cell hitCell;
@@ -555,13 +466,10 @@ public class LockPatternView extends View {
            case MotionEvent.ACTION_DOWN:
                resetPattern();
                hitCell = detectAndAddHit(x, y);
                if (hitCell != null && mOnPatternListener != null) {
                    mPatternInProgress = true;
                    mPatternDisplayMode = DisplayMode.Correct;
                    mOnPatternListener.onPatternStart();
                } else if (mOnPatternListener != null) {
                    mPatternInProgress = false;
                    mOnPatternListener.onPatternCleared();
                if (hitCell != null && mEventListener != null) {
                    mEventListener.onPatternStart();
                } else if (mEventListener != null) {
                    mEventListener.onPatternCleared();
                }
                if (hitCell != null) {
                    final float startX = getCenterXForColumn(hitCell.column);
@@ -584,9 +492,8 @@ public class LockPatternView extends View {
                return true;
            case MotionEvent.ACTION_UP:
                // report pattern detected
                if (!mPattern.isEmpty() && mOnPatternListener != null) {
                    mPatternInProgress = false;
                    mOnPatternListener.onPatternDetected(mPattern);
                if (!mPattern.isEmpty() && mEventListener != null) {
                    mEventListener.onPatternDetected(mPattern);
                    invalidate();
                }
                if (PROFILE_DRAWING) {
@@ -600,9 +507,8 @@ public class LockPatternView extends View {
                final int patternSizePreHitDetect = mPattern.size();
                hitCell = detectAndAddHit(x, y);
                final int patternSize = mPattern.size();
                if (hitCell != null && (mOnPatternListener != null) && (patternSize == 1)) {
                    mPatternInProgress = true;
                    mOnPatternListener.onPatternStart();
                if (hitCell != null && (mEventListener != null) && (patternSize == 1)) {
                    mEventListener.onPatternStart();
                }
                // note current x and y for rubber banding of in progress
                // patterns
@@ -615,7 +521,7 @@ public class LockPatternView extends View {
                    mInProgressX = x;
                    mInProgressY = y;

                    if (mPatternInProgress && patternSize > 0) {
                    if (mState == State.Record && patternSize > 0) {
                        final ArrayList<Cell> pattern = mPattern;
                        final float radius = mSquareWidth * mDiameterFactor * 0.5f;

@@ -718,9 +624,8 @@ public class LockPatternView extends View {
                return true;
            case MotionEvent.ACTION_CANCEL:
                resetPattern();
                if (mOnPatternListener != null) {
                    mPatternInProgress = false;
                    mOnPatternListener.onPatternCleared();
                if (mEventListener != null) {
                    mEventListener.onPatternCleared();
                }
                if (PROFILE_DRAWING) {
                    if (mDrawingProfilingStarted) {
@@ -747,7 +652,7 @@ public class LockPatternView extends View {
        final int count = pattern.size();
        final boolean[][] drawLookup = mPatternDrawLookup;

        if (mPatternDisplayMode == DisplayMode.Animate) {
        if (mState == State.Replay) {

            // figure out which circles to draw

@@ -802,7 +707,7 @@ 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 || mState == State.Incorrect);
        if (drawPath) {
            boolean anyCircles = false;
            for (int i = 0; i < count; i++) {
@@ -826,7 +731,7 @@ public class LockPatternView extends View {
            }

            // add last in progress section
            if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate)
            if ((mState == State.Record || mState == State.Replay)
                    && anyCircles) {
                currentPath.lineTo(mInProgressX, mInProgressY);
            }
@@ -872,7 +777,7 @@ public class LockPatternView extends View {
    }

    private void drawArrow(Canvas canvas, float leftX, float topY, Cell start, Cell end) {
        boolean green = mPatternDisplayMode != DisplayMode.Wrong;
        boolean green = mState != State.Incorrect;

        final int endRow = end.row;
        final int startRow = start.row;
@@ -913,25 +818,25 @@ public class LockPatternView extends View {
        Bitmap outerCircle;
        Bitmap innerCircle;

        if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)) {
        if (!partOfPattern || (mInStealthMode && mState != State.Incorrect)) {
            // unselected circle
            outerCircle = mBitmapCircleDefault;
            innerCircle = mBitmapBtnDefault;
        } else if (mPatternInProgress) {
        } else if (mState == State.Record) {
            // user is in middle of drawing a pattern
            outerCircle = mBitmapCircleGreen;
            innerCircle = mBitmapBtnTouched;
        } else if (mPatternDisplayMode == DisplayMode.Wrong) {
        } else if (mState == State.Incorrect) {
            // the pattern is wrong
            outerCircle = mBitmapCircleRed;
            innerCircle = mBitmapBtnDefault;
        } else if (mPatternDisplayMode == DisplayMode.Correct ||
                mPatternDisplayMode == DisplayMode.Animate) {
        } else if (mState == State.Correct ||
                mState == State.Replay) {
            // the pattern is correct
            outerCircle = mBitmapCircleGreen;
            innerCircle = mBitmapBtnDefault;
        } else {
            throw new IllegalStateException("unknown display mode " + mPatternDisplayMode);
            throw new IllegalStateException("unknown display mode " + mState);
        }

        final int width = mBitmapWidth;
@@ -952,7 +857,7 @@ public class LockPatternView extends View {
        Parcelable superState = super.onSaveInstanceState();
        return new SavedState(superState,
                LockPatternUtils.patternToString(mPattern),
                mPatternDisplayMode.ordinal(),
                mState.ordinal(),
                mInputEnabled, mInStealthMode, mTactileFeedbackEnabled);
    }

@@ -960,10 +865,10 @@ public class LockPatternView extends View {
    protected void onRestoreInstanceState(Parcelable state) {
        final SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        setPattern(
                DisplayMode.Correct,
        DragLock.this.setPattern(
                State.Correct,
                LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
        mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
        mState = State.values()[ss.getState()];
        mInputEnabled = ss.isInputEnabled();
        mInStealthMode = ss.isInStealthMode();
        mTactileFeedbackEnabled = ss.isTactileFeedbackEnabled();
@@ -975,7 +880,7 @@ public class LockPatternView extends View {
    private static class SavedState extends BaseSavedState {

        private final String mSerializedPattern;
        private final int mDisplayMode;
        private final int mState;
        private final boolean mInputEnabled;
        private final boolean mInStealthMode;
        private final boolean mTactileFeedbackEnabled;
@@ -987,7 +892,7 @@ public class LockPatternView extends View {
                boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
            super(superState);
            mSerializedPattern = serializedPattern;
            mDisplayMode = displayMode;
            mState = displayMode;
            mInputEnabled = inputEnabled;
            mInStealthMode = inStealthMode;
            mTactileFeedbackEnabled = tactileFeedbackEnabled;
@@ -999,7 +904,7 @@ public class LockPatternView extends View {
        private SavedState(Parcel in) {
            super(in);
            mSerializedPattern = in.readString();
            mDisplayMode = in.readInt();
            mState = in.readInt();
            mInputEnabled = (Boolean) in.readValue(null);
            mInStealthMode = (Boolean) in.readValue(null);
            mTactileFeedbackEnabled = (Boolean) in.readValue(null);
@@ -1009,8 +914,8 @@ public class LockPatternView extends View {
            return mSerializedPattern;
        }

        public int getDisplayMode() {
            return mDisplayMode;
        public int getState() {
            return mState;
        }

        public boolean isInputEnabled() {
@@ -1029,7 +934,7 @@ public class LockPatternView extends View {
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeString(mSerializedPattern);
            dest.writeInt(mDisplayMode);
            dest.writeInt(mState);
            dest.writeValue(mInputEnabled);
            dest.writeValue(mInStealthMode);
            dest.writeValue(mTactileFeedbackEnabled);
+96 −0
Original line number Diff line number Diff line
package com.android.internal.widget;

import java.util.List;

import android.view.View;

public interface LockPattern {
    public static class Cell {
        int row;
        int column;

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

        /**
         * @param row The row of the cell.
         * @param column The column of the cell.
         */
        private Cell(int row, int column) {
            checkRange(row, column);
            this.row = row;
            this.column = column;
        }

        public int getRow() {
            return row;
        }

        public int getColumn() {
            return column;
        }

        /**
         * @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);
            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");
            }
            if (column < 0 || column > 2) {
                throw new IllegalArgumentException("column must be in range 0-2");
            }
        }

        public String toString() {
            return "(row=" + row + ",clmn=" + column + ")";
        }
    }

    /**
     * How to display the current pattern.
     */
    public enum State {
        Record,
        Replay,
        Incorrect,
        Correct
    }

    /**
     * The call back interface for detecting patterns entered by the user.
     */
    public static interface EventListener {
        void onPatternStart();
        void onPatternCleared();
        void onUserInteraction();
        void onPatternDetected(List<Cell> pattern);
    }

    public boolean isTactileFeedbackEnabled();
    public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled);
    public boolean isInStealthMode();
    public void setInStealthMode(boolean inStealthMode);
    public void setEventListener(EventListener eventListener);
    public void setPattern(State state, List<Cell> pattern);
    public void setState(State state);
    public void clearPattern();
    public void disableInput();
    public void enableInput();
    public int getCorrectDelay();
    public int getIncorrectDelay();
    public View getView();
}
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.widget;

import android.content.ContentResolver;
import android.content.Context;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;

public class LockPatternFactory {
    public static LockPattern inject(FrameLayout container) {
        Context context = container.getContext();
        ContentResolver resolver = context.getContentResolver();

        LockPatternUtils utils = new LockPatternUtils(resolver);

        LockPattern pattern = utils.isPinLockingEnabled()
            ? new PinLock(context)
            : new DragLock(context);

        container.addView(
            pattern.getView(),
            new FrameLayout.LayoutParams(
                LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT));

        return pattern;
    }
}
+38 −24
Original line number Diff line number Diff line
@@ -16,22 +16,21 @@

package com.android.internal.widget;

import android.content.ContentResolver;
import android.os.SystemClock;
import android.provider.Settings;
import android.security.MessageDigest;
import android.text.TextUtils;
import android.util.Log;

import com.google.android.collect.Lists;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.content.ContentResolver;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

/**
 * Utilities for the lock patten and its settings.
 */
@@ -79,6 +78,7 @@ public class LockPatternUtils {
    private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
    private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
    private final static String PATTERN_EVER_CHOSEN = "lockscreen.patterneverchosen";
    private static final String PIN_BASED_LOCKING_ENABLED = "lockscreen.pinbased";

    private final ContentResolver mContentResolver;

@@ -102,7 +102,7 @@ public class LockPatternUtils {
     * @param pattern The pattern to check.
     * @return Whether the pattern matchees the stored one.
     */
    public boolean checkPattern(List<LockPatternView.Cell> pattern) {
    public boolean checkPattern(List<LockPattern.Cell> pattern) {
        try {
            // Read all the bytes from the file
            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
@@ -153,7 +153,7 @@ public class LockPatternUtils {
     * Save a lock pattern.
     * @param pattern The new pattern to save.
     */
    public void saveLockPattern(List<LockPatternView.Cell> pattern) {
    public void saveLockPattern(List<LockPattern.Cell> pattern) {
        // Compute the hash
        final byte[] hash  = LockPatternUtils.patternToHash(pattern);
        try {
@@ -181,13 +181,13 @@ public class LockPatternUtils {
     * @param string The pattern serialized with {@link #patternToString}
     * @return The pattern.
     */
    public static List<LockPatternView.Cell> stringToPattern(String string) {
        List<LockPatternView.Cell> result = Lists.newArrayList();
    public static List<LockPattern.Cell> stringToPattern(String string) {
        List<LockPattern.Cell> result = new ArrayList<LockPattern.Cell>();

        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(LockPattern.Cell.of(b / 3, b % 3));
        }
        return result;
    }
@@ -197,7 +197,7 @@ public class LockPatternUtils {
     * @param pattern The pattern.
     * @return The pattern in string form.
     */
    public static String patternToString(List<LockPatternView.Cell> pattern) {
    public static String patternToString(List<LockPattern.Cell> pattern) {
        if (pattern == null) {
            return "";
        }
@@ -205,7 +205,7 @@ public class LockPatternUtils {

        byte[] res = new byte[patternSize];
        for (int i = 0; i < patternSize; i++) {
            LockPatternView.Cell cell = pattern.get(i);
            LockPattern.Cell cell = pattern.get(i);
            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
        }
        return new String(res);
@@ -218,7 +218,7 @@ public class LockPatternUtils {
     * @param pattern the gesture pattern.
     * @return the hash of the pattern in a byte array.
     */
    static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
    static byte[] patternToHash(List<LockPattern.Cell> pattern) {
        if (pattern == null) {
            return null;
        }
@@ -226,7 +226,7 @@ public class LockPatternUtils {
        final int patternSize = pattern.size();
        byte[] res = new byte[patternSize];
        for (int i = 0; i < patternSize; i++) {
            LockPatternView.Cell cell = pattern.get(i);
            LockPattern.Cell cell = pattern.get(i);
            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
        }
        try {
@@ -273,6 +273,20 @@ public class LockPatternUtils {
        return getBoolean(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
    }

    /**
     * Set whether PIN-based locking is enabled.
     */
    public void setPinLockingEnabled(boolean enabled) {
        setBoolean(PIN_BASED_LOCKING_ENABLED, enabled);
    }

    /**
     * @return Whether PIN-based locking is enabled.
     */
    public boolean isPinLockingEnabled() {
        return getBoolean(PIN_BASED_LOCKING_ENABLED);
    }

    /**
     * Set whether tactile feedback for the pattern is enabled.
     */
+669 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading