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

Commit 329d20d5 authored by Blazej Magnowski's avatar Blazej Magnowski Committed by Android (Google) Code Review
Browse files

Merge "added Classifiers and Evaluators"

parents 434a481b 68d0c9b1
Loading
Loading
Loading
Loading
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.systemui.classifier;

import android.view.MotionEvent;

import java.util.HashMap;

/**
 * A classifier which looks at the speed and distance between successive points of a Stroke.
 * It looks at two consecutive speeds between two points and calculates the ratio between them.
 * The final result is the maximum of these values. It does the same for distances. If some speed
 * or distance is equal to zero then the ratio between this and the next part is not calculated. To
 * the duration of each part there is added one nanosecond so that it is always possible to
 * calculate the speed of a part.
 */
public class AccelerationClassifier extends StrokeClassifier {
    private final HashMap<Stroke, Data> mStrokeMap = new HashMap<>();

    public AccelerationClassifier(ClassifierData classifierData) {
        mClassifierData = classifierData;
    }

    @Override
    public void onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();

        if (action == MotionEvent.ACTION_DOWN) {
            mStrokeMap.clear();
        }

        for (int i = 0; i < event.getPointerCount(); i++) {
            Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
            Point point = stroke.getPoints().get(stroke.getPoints().size() - 1);
            if (mStrokeMap.get(stroke) == null) {
                mStrokeMap.put(stroke, new Data(point));
            } else {
                mStrokeMap.get(stroke).addPoint(point);
            }
        }
    }

    @Override
    public float getFalseTouchEvaluation(int type, Stroke stroke) {
        Data data = mStrokeMap.get(stroke);
        return SpeedRatioEvaluator.evaluate(data.maxSpeedRatio)
                + DistanceRatioEvaluator.evaluate(data.maxDistanceRatio);
    }

    private static class Data {
        public Point previousPoint;
        public float previousSpeed;
        public float previousDistance;
        public float maxSpeedRatio;
        public float maxDistanceRatio;

        public Data(Point point) {
            previousPoint = point;
            previousSpeed = previousDistance = 0.0f;
            maxDistanceRatio = maxSpeedRatio = 0.0f;
        }

        public void addPoint(Point point) {
            float distance = previousPoint.dist(point);
            float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1);
            float speed = distance / duration;
            if (previousDistance != 0.0f) {
                maxDistanceRatio = Math.max(maxDistanceRatio, distance / previousDistance);
            }

            if (previousSpeed != 0.0f) {
                maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed);
            }

            previousDistance = distance;
            previousSpeed = speed;
            previousPoint = point;
        }
    }
}
 No newline at end of file
+43 −22
Original line number Diff line number Diff line
@@ -29,10 +29,15 @@ import java.util.List;
 * For each stroke it keeps its last three points. If some successive points are the same, it
 * ignores the repetitions. If a new point is added, the classifier calculates the angle between
 * the last three points. After that, it calculates the difference between this angle and the
 * previously calculated angle. The return value of the classifier is the variance of the
 * differences from a stroke. To the differences there is artificially added value 0.0 and the
 * difference between the first angle and PI (angles are in radians). It helps with strokes which
 * have few points and punishes more strokes which are not smooth.
 * previously calculated angle. Then it calculates the variance of the differences from a stroke.
 * To the differences there is artificially added value 0.0 and the difference between the first
 * angle and PI (angles are in radians). It helps with strokes which have few points and punishes
 * more strokes which are not smooth. This classifier also tries to split the stroke into two parts
 * int the place in which the biggest angle is. It calculates the angle variance of the two parts
 * and sums them up. The reason the classifier is doing this, is because some human swipes at the
 * beginning go for a moment in one direction and then they rapidly change direction for the rest
 * of the stroke (like a tick). The final result is the minimum of angle variance of the whole
 * stroke and the sum of angle variances of the two parts split up.
 */
public class AnglesVarianceClassifier extends StrokeClassifier {
    private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
@@ -61,21 +66,28 @@ public class AnglesVarianceClassifier extends StrokeClassifier {

    @Override
    public float getFalseTouchEvaluation(int type, Stroke stroke) {
        return mStrokeMap.get(stroke).getAnglesVariance();
        return AnglesVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
    }

    private class Data {
    private static class Data {
        private List<Point> mLastThreePoints = new ArrayList<>();
        private float mFirstAngleVariance;
        private float mPreviousAngle;
        private float mBiggestAngle;
        private float mSumSquares;
        private float mSecondSumSquares;
        private float mSum;
        private float mSecondSum;
        private float mCount;
        private float mSecondCount;

        public Data() {
            mFirstAngleVariance = 0.0f;
            mPreviousAngle = (float) Math.PI;
            mSumSquares = 0.0f;
            mSum = 0.0f;
            mCount = 1.0f;
            mBiggestAngle = 0.0f;
            mSumSquares = mSecondSumSquares = 0.0f;
            mSum = mSecondSum = 0.0f;
            mCount = mSecondCount = 1.0f;
        }

        public void addPoint(Point point) {
@@ -87,10 +99,26 @@ public class AnglesVarianceClassifier extends StrokeClassifier {
                if (mLastThreePoints.size() == 4) {
                    mLastThreePoints.remove(0);

                    float angle = getAngle(mLastThreePoints.get(0), mLastThreePoints.get(1),
                    float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
                            mLastThreePoints.get(2));

                    float difference = angle - mPreviousAngle;

                    // If this is the biggest angle of the stroke so then we save the value of
                    // the angle variance so far and start to count the values for the angle
                    // variance of the second part.
                    if (mBiggestAngle < angle) {
                        mBiggestAngle = angle;
                        mFirstAngleVariance = getAnglesVariance(mSumSquares, mSum, mCount);
                        mSecondSumSquares = 0.0f;
                        mSecondSum = 0.0f;
                        mSecondCount = 1.0f;
                    } else {
                        mSecondSum += difference;
                        mSecondSumSquares += difference * difference;
                        mSecondCount += 1.0;
                    }

                    mSum += difference;
                    mSumSquares += difference * difference;
                    mCount += 1.0;
@@ -99,21 +127,14 @@ public class AnglesVarianceClassifier extends StrokeClassifier {
            }
        }

        private float getAngle(Point a, Point b, Point c) {
            float dist1 = a.dist(b);
            float dist2 = b.dist(c);
            float crossProduct = b.crossProduct(a, c);
            float dotProduct = b.dotProduct(a, c);
            float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
            float angle = (float) Math.acos(cos);
            if (crossProduct < 0.0) {
                angle = 2.0f * (float) Math.PI - angle;
            }
            return angle;
        public float getAnglesVariance(float sumSquares, float sum, float count) {
            return sumSquares / count - (sum / count) * (sum / count);
        }

        public float getAnglesVariance() {
            return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
            return Math.min(getAnglesVariance(mSumSquares, mSum, mCount),
                    mFirstAngleVariance + getAnglesVariance(mSecondSumSquares, mSecondSum,
                            mSecondCount));
        }
    }
}
 No newline at end of file
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.systemui.classifier;

public class AnglesVarianceEvaluator {
    public static float evaluate(float value) {
        float evaluation = 0.0f;
        if (value > 0.05) evaluation++;
        if (value > 0.10) evaluation++;
        if (value > 0.20) evaluation++;
        if (value > 0.40) evaluation++;
        if (value > 0.80) evaluation++;
        if (value > 1.50) evaluation++;
        return evaluation;
    }
}
+6 −2
Original line number Diff line number Diff line
@@ -28,8 +28,12 @@ import java.util.ArrayList;
public class ClassifierData {
    private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
    private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
    private float mXdpi;
    private float mYdpi;

    public ClassifierData() {
    public ClassifierData(float xdpi, float ydpi) {
        mXdpi = xdpi;
        mYdpi = ydpi;
    }

    public void update(MotionEvent event) {
@@ -42,7 +46,7 @@ public class ClassifierData {
        for (int i = 0; i < event.getPointerCount(); i++) {
            int id = event.getPointerId(i);
            if (mCurrentStrokes.get(id) == null) {
                mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano()));
                mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano(), mXdpi, mYdpi));
            }
            mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
                    event.getEventTimeNano());
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.systemui.classifier;

public class DistanceRatioEvaluator {
    public static float evaluate(float value) {
        float evaluation = 0.0f;
        if (value <= 1.0) evaluation++;
        if (value <= 0.5) evaluation++;
        if (value > 4.0) evaluation++;
        if (value > 7.0) evaluation++;
        if (value > 14.0) evaluation++;
        return evaluation;
    }
}
Loading