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 17package com.android.incallui.answer.impl.classifier; 18 19import android.hardware.Sensor; 20import android.hardware.SensorEvent; 21import android.view.MotionEvent; 22import java.util.concurrent.TimeUnit; 23 24/** 25 * A classifier which looks at the proximity sensor during the gesture. It calculates the percentage 26 * the proximity sensor showing the near state during the whole gesture 27 */ 28class ProximityClassifier extends GestureClassifier { 29 private long gestureStartTimeNano; 30 private long nearStartTimeNano; 31 private long nearDuration; 32 private boolean near; 33 private float averageNear; 34 35 public ProximityClassifier(ClassifierData classifierData) {} 36 37 @Override 38 public String getTag() { 39 return "PROX"; 40 } 41 42 @Override 43 public void onSensorChanged(SensorEvent event) { 44 if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) { 45 update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp); 46 } 47 } 48 49 @Override 50 public void onTouchEvent(MotionEvent event) { 51 int action = event.getActionMasked(); 52 53 if (action == MotionEvent.ACTION_DOWN) { 54 gestureStartTimeNano = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()); 55 nearStartTimeNano = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()); 56 nearDuration = 0; 57 } 58 59 if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 60 update(near, TimeUnit.MILLISECONDS.toNanos(event.getEventTime())); 61 long duration = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()) - gestureStartTimeNano; 62 63 if (duration == 0) { 64 averageNear = near ? 1.0f : 0.0f; 65 } else { 66 averageNear = (float) nearDuration / (float) duration; 67 } 68 } 69 } 70 71 /** 72 * @param near is the sensor showing the near state right now 73 * @param timestampNano time of this event in nanoseconds 74 */ 75 private void update(boolean near, long timestampNano) { 76 // This if is necessary because MotionEvents and SensorEvents do not come in 77 // chronological order 78 if (timestampNano > nearStartTimeNano) { 79 // if the state before was near then add the difference of the current time and 80 // mNearStartTimeNano to mNearDuration. 81 if (this.near) { 82 nearDuration += timestampNano - nearStartTimeNano; 83 } 84 85 // if the new state is near, set mNearStartTimeNano equal to this moment. 86 if (near) { 87 nearStartTimeNano = timestampNano; 88 } 89 } 90 this.near = near; 91 } 92 93 @Override 94 public float getFalseTouchEvaluation() { 95 return ProximityEvaluator.evaluate(averageNear); 96 } 97} 98