Loading packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java +11 −48 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.classifier; import android.hardware.SensorEvent; import android.view.MotionEvent; import java.lang.Math; Loading @@ -27,27 +26,19 @@ import java.util.List; /** * A classifier which calculates the variance of differences between successive angles in a stroke. * 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. If there are multiple strokes created at once, the classifier sums up the * variances of all the strokes. Also the value is multiplied by HISTORY_FACTOR after each * INTERVAL milliseconds. * 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. */ public class AnglesVarianceClassifier extends Classifier { private final float INTERVAL = 10.0f; private final float CLEAR_HISTORY = 500f; private final float HISTORY_FACTOR = 0.9f; public class AnglesVarianceClassifier extends StrokeClassifier { private HashMap<Stroke, Data> mStrokeMap = new HashMap<>(); private float mValue; private long mLastUpdate; public AnglesVarianceClassifier(ClassifierData classifierData) { mClassifierData = classifierData; mValue = 0.0f; mLastUpdate = System.currentTimeMillis(); } @Override Loading @@ -65,40 +56,12 @@ public class AnglesVarianceClassifier extends Classifier { mStrokeMap.put(stroke, new Data()); } mStrokeMap.get(stroke).addPoint(stroke.getPoints().get(stroke.getPoints().size() - 1)); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) { decayValue(); mValue += mStrokeMap.get(stroke).getAnglesVariance(); } } } /** * Decreases mValue through time */ private void decayValue() { long currentTimeMillis = System.currentTimeMillis(); if (currentTimeMillis - mLastUpdate > CLEAR_HISTORY) { mValue = 0.0f; } else { mValue *= Math.pow(HISTORY_FACTOR, (float) (currentTimeMillis - mLastUpdate) / INTERVAL); } mLastUpdate = currentTimeMillis; } @Override public void onSensorChanged(SensorEvent event) { } @Override public float getFalseTouchEvaluation(int type) { decayValue(); float currentValue = 0.0f; for (Data data: mStrokeMap.values()) { currentValue += data.getAnglesVariance(); } return (float) (mValue + currentValue); public float getFalseTouchEvaluation(int type, Stroke stroke) { return mStrokeMap.get(stroke).getAnglesVariance(); } private class Data { Loading Loading @@ -150,7 +113,7 @@ public class AnglesVarianceClassifier extends Classifier { } public float getAnglesVariance() { return mSumSquares / mCount + (mSum / mCount) * (mSum / mCount); return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount); } } } No newline at end of file packages/SystemUI/src/com/android/systemui/classifier/Classifier.java +2 −8 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.hardware.SensorEvent; import android.view.MotionEvent; /** * An interface for classifiers for touch and sensor events. * An abstract class for classifiers for touch and sensor events. */ public abstract class Classifier { public static final int QUICK_SETTINGS = 0; Loading @@ -30,6 +30,7 @@ public abstract class Classifier { public static final int UNLOCK = 4; public static final int LEFT_AFFORDANCE = 5; public static final int RIGHT_AFFORDANCE = 6; public static final int GENERIC = 7; /** * Contains all the information about touch events from which the classifier can query Loading @@ -47,11 +48,4 @@ public abstract class Classifier { */ public void onSensorChanged(SensorEvent event) { } /** * @param type the type of action for which this method is called * @return a nonnegative value which is used to determine whether this a false touch. The * bigger the value the greater the chance that this a false touch. */ public abstract float getFalseTouchEvaluation(int type); } packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java +18 −0 Original line number Diff line number Diff line Loading @@ -19,21 +19,26 @@ package com.android.systemui.classifier; import android.util.SparseArray; import android.view.MotionEvent; import java.util.ArrayList; /** * Contains data which is used to classify interaction sequences on the lockscreen. It does, for * example, provide information on the current touch state. */ public class ClassifierData { private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>(); private ArrayList<Stroke> mEndingStrokes = new ArrayList<>(); public ClassifierData() { } public void update(MotionEvent event) { mEndingStrokes.clear(); int action = event.getActionMasked(); if (action == MotionEvent.ACTION_DOWN) { mCurrentStrokes.clear(); } for (int i = 0; i < event.getPointerCount(); i++) { int id = event.getPointerId(i); if (mCurrentStrokes.get(id) == null) { Loading @@ -41,10 +46,16 @@ public class ClassifierData { } mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i), event.getEventTimeNano()); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) { mEndingStrokes.add(getStroke(id)); } } } public void cleanUp(MotionEvent event) { mEndingStrokes.clear(); int action = event.getActionMasked(); for (int i = 0; i < event.getPointerCount(); i++) { int id = event.getPointerId(i); Loading @@ -55,6 +66,13 @@ public class ClassifierData { } } /** * @return the list of Strokes which are ending in the recently added MotionEvent */ public ArrayList<Stroke> getEndingStrokes() { return mEndingStrokes; } /** * @param id the id from MotionEvent * @return the Stroke assigned to the id Loading packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +11 −3 Original line number Diff line number Diff line Loading @@ -126,11 +126,10 @@ public class FalsingManager implements SensorEventListener { } /** * @param type the type of action for which this method is called * @return true if the classifier determined that this is not a human interacting with the phone */ public boolean isFalseTouch(int type) { return mHumanInteractionClassifier.getFalseTouchEvaluation(type) > 0.5; public boolean isFalseTouch() { return mHumanInteractionClassifier.isFalseTouch(); } @Override Loading Loading @@ -189,6 +188,7 @@ public class FalsingManager implements SensorEventListener { } public void onQsDown() { mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS); mDataCollector.onQsDown(); } Loading @@ -197,6 +197,7 @@ public class FalsingManager implements SensorEventListener { } public void onTrackingStarted() { mHumanInteractionClassifier.setType(Classifier.UNLOCK); mDataCollector.onTrackingStarted(); } Loading @@ -217,6 +218,7 @@ public class FalsingManager implements SensorEventListener { } public void onNotificatonStartDraggingDown() { mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN); mDataCollector.onNotificatonStartDraggingDown(); } Loading @@ -229,6 +231,7 @@ public class FalsingManager implements SensorEventListener { } public void onNotificatonStartDismissing() { mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS); mDataCollector.onNotificatonStartDismissing(); } Loading @@ -245,6 +248,11 @@ public class FalsingManager implements SensorEventListener { } public void onAffordanceSwipingStarted(boolean rightCorner) { if (rightCorner) { mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE); } else { mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE); } mDataCollector.onAffordanceSwipingStarted(rightCorner); } Loading packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java 0 → 100644 +32 −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; /** * An abstract class for classifiers which classify the whole gesture (all the strokes which * occurred from DOWN event to UP/CANCEL event) */ public abstract class GestureClassifier extends Classifier { /** * @param type the type of action for which this method is called * @return a non-negative value which is used to determine whether the most recent gesture is a * false interaction. The bigger the value the greater the chance that this a false * interaction. */ public abstract float getFalseTouchEvaluation(int type); } Loading
packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java +11 −48 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.classifier; import android.hardware.SensorEvent; import android.view.MotionEvent; import java.lang.Math; Loading @@ -27,27 +26,19 @@ import java.util.List; /** * A classifier which calculates the variance of differences between successive angles in a stroke. * 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. If there are multiple strokes created at once, the classifier sums up the * variances of all the strokes. Also the value is multiplied by HISTORY_FACTOR after each * INTERVAL milliseconds. * 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. */ public class AnglesVarianceClassifier extends Classifier { private final float INTERVAL = 10.0f; private final float CLEAR_HISTORY = 500f; private final float HISTORY_FACTOR = 0.9f; public class AnglesVarianceClassifier extends StrokeClassifier { private HashMap<Stroke, Data> mStrokeMap = new HashMap<>(); private float mValue; private long mLastUpdate; public AnglesVarianceClassifier(ClassifierData classifierData) { mClassifierData = classifierData; mValue = 0.0f; mLastUpdate = System.currentTimeMillis(); } @Override Loading @@ -65,40 +56,12 @@ public class AnglesVarianceClassifier extends Classifier { mStrokeMap.put(stroke, new Data()); } mStrokeMap.get(stroke).addPoint(stroke.getPoints().get(stroke.getPoints().size() - 1)); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) { decayValue(); mValue += mStrokeMap.get(stroke).getAnglesVariance(); } } } /** * Decreases mValue through time */ private void decayValue() { long currentTimeMillis = System.currentTimeMillis(); if (currentTimeMillis - mLastUpdate > CLEAR_HISTORY) { mValue = 0.0f; } else { mValue *= Math.pow(HISTORY_FACTOR, (float) (currentTimeMillis - mLastUpdate) / INTERVAL); } mLastUpdate = currentTimeMillis; } @Override public void onSensorChanged(SensorEvent event) { } @Override public float getFalseTouchEvaluation(int type) { decayValue(); float currentValue = 0.0f; for (Data data: mStrokeMap.values()) { currentValue += data.getAnglesVariance(); } return (float) (mValue + currentValue); public float getFalseTouchEvaluation(int type, Stroke stroke) { return mStrokeMap.get(stroke).getAnglesVariance(); } private class Data { Loading Loading @@ -150,7 +113,7 @@ public class AnglesVarianceClassifier extends Classifier { } public float getAnglesVariance() { return mSumSquares / mCount + (mSum / mCount) * (mSum / mCount); return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount); } } } No newline at end of file
packages/SystemUI/src/com/android/systemui/classifier/Classifier.java +2 −8 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.hardware.SensorEvent; import android.view.MotionEvent; /** * An interface for classifiers for touch and sensor events. * An abstract class for classifiers for touch and sensor events. */ public abstract class Classifier { public static final int QUICK_SETTINGS = 0; Loading @@ -30,6 +30,7 @@ public abstract class Classifier { public static final int UNLOCK = 4; public static final int LEFT_AFFORDANCE = 5; public static final int RIGHT_AFFORDANCE = 6; public static final int GENERIC = 7; /** * Contains all the information about touch events from which the classifier can query Loading @@ -47,11 +48,4 @@ public abstract class Classifier { */ public void onSensorChanged(SensorEvent event) { } /** * @param type the type of action for which this method is called * @return a nonnegative value which is used to determine whether this a false touch. The * bigger the value the greater the chance that this a false touch. */ public abstract float getFalseTouchEvaluation(int type); }
packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java +18 −0 Original line number Diff line number Diff line Loading @@ -19,21 +19,26 @@ package com.android.systemui.classifier; import android.util.SparseArray; import android.view.MotionEvent; import java.util.ArrayList; /** * Contains data which is used to classify interaction sequences on the lockscreen. It does, for * example, provide information on the current touch state. */ public class ClassifierData { private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>(); private ArrayList<Stroke> mEndingStrokes = new ArrayList<>(); public ClassifierData() { } public void update(MotionEvent event) { mEndingStrokes.clear(); int action = event.getActionMasked(); if (action == MotionEvent.ACTION_DOWN) { mCurrentStrokes.clear(); } for (int i = 0; i < event.getPointerCount(); i++) { int id = event.getPointerId(i); if (mCurrentStrokes.get(id) == null) { Loading @@ -41,10 +46,16 @@ public class ClassifierData { } mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i), event.getEventTimeNano()); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) { mEndingStrokes.add(getStroke(id)); } } } public void cleanUp(MotionEvent event) { mEndingStrokes.clear(); int action = event.getActionMasked(); for (int i = 0; i < event.getPointerCount(); i++) { int id = event.getPointerId(i); Loading @@ -55,6 +66,13 @@ public class ClassifierData { } } /** * @return the list of Strokes which are ending in the recently added MotionEvent */ public ArrayList<Stroke> getEndingStrokes() { return mEndingStrokes; } /** * @param id the id from MotionEvent * @return the Stroke assigned to the id Loading
packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +11 −3 Original line number Diff line number Diff line Loading @@ -126,11 +126,10 @@ public class FalsingManager implements SensorEventListener { } /** * @param type the type of action for which this method is called * @return true if the classifier determined that this is not a human interacting with the phone */ public boolean isFalseTouch(int type) { return mHumanInteractionClassifier.getFalseTouchEvaluation(type) > 0.5; public boolean isFalseTouch() { return mHumanInteractionClassifier.isFalseTouch(); } @Override Loading Loading @@ -189,6 +188,7 @@ public class FalsingManager implements SensorEventListener { } public void onQsDown() { mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS); mDataCollector.onQsDown(); } Loading @@ -197,6 +197,7 @@ public class FalsingManager implements SensorEventListener { } public void onTrackingStarted() { mHumanInteractionClassifier.setType(Classifier.UNLOCK); mDataCollector.onTrackingStarted(); } Loading @@ -217,6 +218,7 @@ public class FalsingManager implements SensorEventListener { } public void onNotificatonStartDraggingDown() { mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN); mDataCollector.onNotificatonStartDraggingDown(); } Loading @@ -229,6 +231,7 @@ public class FalsingManager implements SensorEventListener { } public void onNotificatonStartDismissing() { mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS); mDataCollector.onNotificatonStartDismissing(); } Loading @@ -245,6 +248,11 @@ public class FalsingManager implements SensorEventListener { } public void onAffordanceSwipingStarted(boolean rightCorner) { if (rightCorner) { mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE); } else { mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE); } mDataCollector.onAffordanceSwipingStarted(rightCorner); } Loading
packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java 0 → 100644 +32 −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; /** * An abstract class for classifiers which classify the whole gesture (all the strokes which * occurred from DOWN event to UP/CANCEL event) */ public abstract class GestureClassifier extends Classifier { /** * @param type the type of action for which this method is called * @return a non-negative value which is used to determine whether the most recent gesture is a * false interaction. The bigger the value the greater the chance that this a false * interaction. */ public abstract float getFalseTouchEvaluation(int type); }