168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski/* 268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * Copyright (C) 2015 The Android Open Source Project 368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * 468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * Licensed under the Apache License, Version 2.0 (the "License"); 568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * you may not use this file except in compliance with the License. 668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * You may obtain a copy of the License at 768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * 868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * http://www.apache.org/licenses/LICENSE-2.0 968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * 1068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * Unless required by applicable law or agreed to in writing, software 1168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * distributed under the License is distributed on an "AS IS" BASIS, 1268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * See the License for the specific language governing permissions and 1468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * limitations under the License 1568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski */ 1668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 1768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskipackage com.android.systemui.classifier; 1868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 1968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskiimport android.view.MotionEvent; 2068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 2168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskiimport java.util.HashMap; 2268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 2368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski/** 2468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * A classifier which looks at the speed and distance between successive points of a Stroke. 2568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * It looks at two consecutive speeds between two points and calculates the ratio between them. 2668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * The final result is the maximum of these values. It does the same for distances. If some speed 2768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * or distance is equal to zero then the ratio between this and the next part is not calculated. To 2868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * the duration of each part there is added one nanosecond so that it is always possible to 2968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * calculate the speed of a part. 3068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski */ 3168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskipublic class AccelerationClassifier extends StrokeClassifier { 3268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski private final HashMap<Stroke, Data> mStrokeMap = new HashMap<>(); 3368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 3468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public AccelerationClassifier(ClassifierData classifierData) { 3568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski mClassifierData = classifierData; 3668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 3768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 3868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski @Override 39401caaedd871894620accc1d14592c08095b5523Adrian Roos public String getTag() { 40401caaedd871894620accc1d14592c08095b5523Adrian Roos return "ACC"; 41401caaedd871894620accc1d14592c08095b5523Adrian Roos } 42401caaedd871894620accc1d14592c08095b5523Adrian Roos 43401caaedd871894620accc1d14592c08095b5523Adrian Roos @Override 4468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public void onTouchEvent(MotionEvent event) { 4568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski int action = event.getActionMasked(); 4668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 4768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski if (action == MotionEvent.ACTION_DOWN) { 4868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski mStrokeMap.clear(); 4968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 5068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 5168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski for (int i = 0; i < event.getPointerCount(); i++) { 5268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski Stroke stroke = mClassifierData.getStroke(event.getPointerId(i)); 5368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski Point point = stroke.getPoints().get(stroke.getPoints().size() - 1); 5468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski if (mStrokeMap.get(stroke) == null) { 5568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski mStrokeMap.put(stroke, new Data(point)); 5668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } else { 5768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski mStrokeMap.get(stroke).addPoint(point); 5868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 5968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 6068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 6168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 6268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski @Override 6368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public float getFalseTouchEvaluation(int type, Stroke stroke) { 6468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski Data data = mStrokeMap.get(stroke); 6568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski return SpeedRatioEvaluator.evaluate(data.maxSpeedRatio) 6668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski + DistanceRatioEvaluator.evaluate(data.maxDistanceRatio); 6768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 6868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 6968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski private static class Data { 7068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public Point previousPoint; 7168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public float previousSpeed; 7268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public float previousDistance; 7368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public float maxSpeedRatio; 7468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public float maxDistanceRatio; 7568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 7668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public Data(Point point) { 7768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski previousPoint = point; 7868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski previousSpeed = previousDistance = 0.0f; 7968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski maxDistanceRatio = maxSpeedRatio = 0.0f; 8068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 8168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 8268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski public void addPoint(Point point) { 8368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski float distance = previousPoint.dist(point); 8468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1); 8568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski float speed = distance / duration; 8668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski if (previousDistance != 0.0f) { 8768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski maxDistanceRatio = Math.max(maxDistanceRatio, distance / previousDistance); 8868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 8968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 9068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski if (previousSpeed != 0.0f) { 9168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed); 9268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 9368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski 9468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski previousDistance = distance; 9568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski previousSpeed = speed; 9668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski previousPoint = point; 9768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 9868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski } 9968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski}