Home | History | Annotate | Download | only in classifier
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.systemui.classifier;
     18 
     19 import android.util.SparseArray;
     20 import android.view.MotionEvent;
     21 
     22 import java.util.ArrayList;
     23 
     24 /**
     25  * Contains data which is used to classify interaction sequences on the lockscreen. It does, for
     26  * example, provide information on the current touch state.
     27  */
     28 public class ClassifierData {
     29     private static final long MINIMUM_DT_NANOS = 16666666;  // 60Hz
     30     private static final long MINIMUM_DT_SMEAR_NANOS = 2500000;  // 2.5ms
     31 
     32     private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
     33     private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
     34     private final float mDpi;
     35 
     36     public ClassifierData(float dpi) {
     37         mDpi = dpi;
     38     }
     39 
     40     /** Returns true if the event should be considered, false otherwise. */
     41     public boolean update(MotionEvent event) {
     42         // We limit to 60hz sampling. Drop anything happening faster than that.
     43         // Legacy code was created with an assumed sampling rate. As devices increase their
     44         // sampling rate, this creates potentialy false positives.
     45         if (event.getActionMasked() == MotionEvent.ACTION_MOVE
     46                 && mCurrentStrokes.size() != 0
     47                 && event.getEventTimeNano() - mCurrentStrokes.valueAt(0).getLastEventTimeNano()
     48                         < MINIMUM_DT_NANOS - MINIMUM_DT_SMEAR_NANOS) {
     49             return false;
     50         }
     51 
     52         mEndingStrokes.clear();
     53         int action = event.getActionMasked();
     54         if (action == MotionEvent.ACTION_DOWN) {
     55             mCurrentStrokes.clear();
     56         }
     57 
     58         for (int i = 0; i < event.getPointerCount(); i++) {
     59             int id = event.getPointerId(i);
     60             if (mCurrentStrokes.get(id) == null) {
     61                 mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano(), mDpi));
     62             }
     63             mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
     64                     event.getEventTimeNano());
     65 
     66             if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
     67                     || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
     68                 mEndingStrokes.add(getStroke(id));
     69             }
     70         }
     71 
     72         return true;
     73     }
     74 
     75     public void cleanUp(MotionEvent event) {
     76         mEndingStrokes.clear();
     77         int action = event.getActionMasked();
     78         for (int i = 0; i < event.getPointerCount(); i++) {
     79             int id = event.getPointerId(i);
     80             if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
     81                     || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
     82                 mCurrentStrokes.remove(id);
     83             }
     84         }
     85     }
     86 
     87     /**
     88      * @return the list of Strokes which are ending in the recently added MotionEvent
     89      */
     90     public ArrayList<Stroke> getEndingStrokes() {
     91         return mEndingStrokes;
     92     }
     93 
     94     /**
     95      * @param id the id from MotionEvent
     96      * @return the Stroke assigned to the id
     97      */
     98     public Stroke getStroke(int id) {
     99         return mCurrentStrokes.get(id);
    100     }
    101 }
    102