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.incallui.answer.impl.classifier; 18 19 import android.hardware.Sensor; 20 import android.hardware.SensorEvent; 21 import android.view.MotionEvent; 22 import 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 */ 28 class ProximityClassifier extends GestureClassifier { 29 private long mGestureStartTimeNano; 30 private long mNearStartTimeNano; 31 private long mNearDuration; 32 private boolean mNear; 33 private float mAverageNear; 34 ProximityClassifier(ClassifierData classifierData)35 public ProximityClassifier(ClassifierData classifierData) {} 36 37 @Override getTag()38 public String getTag() { 39 return "PROX"; 40 } 41 42 @Override onSensorChanged(SensorEvent event)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 mGestureStartTimeNano = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()); 55 mNearStartTimeNano = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()); 56 mNearDuration = 0; 57 } 58 59 if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 60 update(mNear, TimeUnit.MILLISECONDS.toNanos(event.getEventTime())); 61 long duration = TimeUnit.MILLISECONDS.toNanos(event.getEventTime()) - mGestureStartTimeNano; 62 63 if (duration == 0) { 64 mAverageNear = mNear ? 1.0f : 0.0f; 65 } else { 66 mAverageNear = (float) mNearDuration / (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 > mNearStartTimeNano) { 79 // if the state before was near then add the difference of the current time and 80 // mNearStartTimeNano to mNearDuration. 81 if (mNear) { 82 mNearDuration += timestampNano - mNearStartTimeNano; 83 } 84 85 // if the new state is near, set mNearStartTimeNano equal to this moment. 86 if (near) { 87 mNearStartTimeNano = timestampNano; 88 } 89 } 90 mNear = near; 91 } 92 93 @Override getFalseTouchEvaluation()94 public float getFalseTouchEvaluation() { 95 return ProximityEvaluator.evaluate(mAverageNear); 96 } 97 } 98