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.hardware.Sensor;
2068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskiimport android.hardware.SensorEvent;
2168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskiimport android.view.MotionEvent;
2268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
2368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski/**
2468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * A classifier which looks at the proximity sensor during the gesture. It calculates the percentage
2568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski * the proximity sensor showing the near state during the whole gesture
2668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski */
2768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowskipublic class ProximityClassifier extends GestureClassifier {
2868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private long mGestureStartTimeNano;
2968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private long mNearStartTimeNano;
3068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private long mNearDuration;
3168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private boolean mNear;
3268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private float mAverageNear;
3368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
3468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    public ProximityClassifier(ClassifierData classifierData) {
3568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
3668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
3768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    @Override
38401caaedd871894620accc1d14592c08095b5523Adrian Roos    public String getTag() {
39401caaedd871894620accc1d14592c08095b5523Adrian Roos        return "PROX";
40401caaedd871894620accc1d14592c08095b5523Adrian Roos    }
41401caaedd871894620accc1d14592c08095b5523Adrian Roos
42401caaedd871894620accc1d14592c08095b5523Adrian Roos    @Override
4368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    public void onSensorChanged(SensorEvent event) {
4468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
4568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp);
4668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
4768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
4868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
4968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    @Override
5068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    public void onTouchEvent(MotionEvent event) {
5168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        int action = event.getActionMasked();
5268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
5368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (action == MotionEvent.ACTION_DOWN) {
5468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            mGestureStartTimeNano = event.getEventTimeNano();
5568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            mNearStartTimeNano = event.getEventTimeNano();
5668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            mNearDuration = 0;
5768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
5868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
5968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
6068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            update(mNear, event.getEventTimeNano());
6168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            long duration = event.getEventTimeNano() - mGestureStartTimeNano;
6268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
6368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            if (duration == 0) {
6468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski                mAverageNear = mNear ? 1.0f : 0.0f;
6568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            } else {
6668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski                mAverageNear = (float) mNearDuration / (float) duration;
6768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            }
6868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
6968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
7068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
7168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
7268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    /**
7368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     * @param near is the sensor showing the near state right now
7468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     * @param timestampNano time of this event in nanoseconds
7568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     */
7668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    private void update(boolean near, long timestampNano) {
7768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        // This if is necessary because MotionEvents and SensorEvents do not come in
7868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        // chronological order
7968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (timestampNano > mNearStartTimeNano) {
8068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            // if the state before was near then add the difference of the current time and
8168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            // mNearStartTimeNano to mNearDuration.
8268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            if (mNear) {
8368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski                mNearDuration += timestampNano - mNearStartTimeNano;
8468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            }
8568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
8668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            // if the new state is near, set mNearStartTimeNano equal to this moment.
8768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            if (near) {
8868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski                mNearStartTimeNano = timestampNano;
8968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            }
9068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
9168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        mNear = near;
9268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
9368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
9468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    @Override
9568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    public float getFalseTouchEvaluation(int type) {
9668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        return ProximityEvaluator.evaluate(mAverageNear, type);
9768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
9868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski}
99