summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
blob: 2644bf9f26ce78797d940e23a4e05c25631a1fae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.classifier.brightline;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.provider.DeviceConfig;
import android.view.MotionEvent;


/**
 * False touch if proximity sensor is covered for more than a certain percentage of the gesture.
 *
 * This classifer is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be
 * covered when swiping from the top.
 */
class ProximityClassifier extends FalsingClassifier {

    private static final float PERCENT_COVERED_THRESHOLD = 0.1f;
    private final DistanceClassifier mDistanceClassifier;
    private final float mPercentCoveredThreshold;

    private boolean mNear;
    private long mGestureStartTimeNs;
    private long mPrevNearTimeNs;
    private long mNearDurationNs;
    private float mPercentNear;

    ProximityClassifier(DistanceClassifier distanceClassifier,
            FalsingDataProvider dataProvider) {
        super(dataProvider);
        this.mDistanceClassifier = distanceClassifier;

        mPercentCoveredThreshold = DeviceConfig.getFloat(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD,
                PERCENT_COVERED_THRESHOLD);
    }

    @Override
    void onSessionStarted() {
        mPrevNearTimeNs = 0;
        mPercentNear = 0;
    }

    @Override
    void onSessionEnded() {
        mPrevNearTimeNs = 0;
        mPercentNear = 0;
    }

    @Override
    public void onTouchEvent(MotionEvent motionEvent) {
        int action = motionEvent.getActionMasked();

        if (action == MotionEvent.ACTION_DOWN) {
            mGestureStartTimeNs = motionEvent.getEventTimeNano();
            if (mPrevNearTimeNs > 0) {
                // We only care about if the proximity sensor is triggered while a move event is
                // happening.
                mPrevNearTimeNs = motionEvent.getEventTimeNano();
            }
            logDebug("Gesture start time: " + mGestureStartTimeNs);
            mNearDurationNs = 0;
        }

        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            update(mNear, motionEvent.getEventTimeNano());
            long duration = motionEvent.getEventTimeNano() - mGestureStartTimeNs;

            logDebug("Gesture duration, Proximity duration: " + duration + ", " + mNearDurationNs);

            if (duration == 0) {
                mPercentNear = mNear ? 1.0f : 0.0f;
            } else {
                mPercentNear = (float) mNearDurationNs / (float) duration;
            }
        }

    }

    @Override
    public void onSensorEvent(SensorEvent sensorEvent) {
        if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY) {
            logDebug("Sensor is: " + (sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange())
                    + " at time " + sensorEvent.timestamp);
            update(
                    sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange(),
                    sensorEvent.timestamp);
        }
    }

    @Override
    public boolean isFalseTouch() {
        if (getInteractionType() == QUICK_SETTINGS) {
            return false;
        }

        logInfo("Percent of gesture in proximity: " + mPercentNear);

        if (mPercentNear > mPercentCoveredThreshold) {
            return !mDistanceClassifier.isLongSwipe();
        }

        return false;
    }

    /**
     * @param near        is the sensor showing the near state right now
     * @param timeStampNs time of this event in nanoseconds
     */
    private void update(boolean near, long timeStampNs) {
        if (mPrevNearTimeNs != 0 && timeStampNs > mPrevNearTimeNs && mNear) {
            mNearDurationNs += timeStampNs - mPrevNearTimeNs;
            logDebug("Updating duration: " + mNearDurationNs);
        }

        if (near) {
            logDebug("Set prevNearTimeNs: " + timeStampNs);
            mPrevNearTimeNs = timeStampNs;
        }

        mNear = near;
    }
}