blob: ce82bbfb1512a6ef13470fd1bfb32eb5e074c84c [file] [log] [blame]
Dave Mankoff07fb7b72019-06-10 16:36:19 -04001/*
2 * Copyright (C) 2019 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.systemui.classifier.brightline;
18
Dave Mankoff1dee0342019-07-11 17:44:54 -040019import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_REMAIN_LOCKED;
20import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS;
21
Dave Mankoff07fb7b72019-06-10 16:36:19 -040022import android.hardware.Sensor;
23import android.hardware.SensorEvent;
24import android.hardware.SensorEventListener;
25import android.hardware.SensorManager;
26import android.net.Uri;
27import android.util.Log;
28import android.view.MotionEvent;
29
Dave Mankoff1dee0342019-07-11 17:44:54 -040030import com.android.internal.logging.MetricsLogger;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040031import com.android.systemui.classifier.Classifier;
32import com.android.systemui.plugins.FalsingManager;
33
34import java.io.PrintWriter;
35import java.util.ArrayList;
36import java.util.List;
37import java.util.concurrent.ExecutorService;
38import java.util.concurrent.Executors;
39
40/**
41 * FalsingManager designed to make clear why a touch was rejected.
42 */
43public class BrightLineFalsingManager implements FalsingManager {
44
45 static final boolean DEBUG = false;
46 private static final String TAG = "FalsingManagerPlugin";
47
48 private final SensorManager mSensorManager;
49 private final FalsingDataProvider mDataProvider;
50 private boolean mSessionStarted;
Dave Mankoff1dee0342019-07-11 17:44:54 -040051 private MetricsLogger mMetricsLogger;
52 private int mIsFalseTouchCalls;
Dave Mankoff1a6d9e62019-07-26 13:50:08 -040053 private boolean mShowingAod;
54 private boolean mScreenOn;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040055
56 private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
57
58 private final List<FalsingClassifier> mClassifiers;
59
60 private SensorEventListener mSensorEventListener = new SensorEventListener() {
61 @Override
62 public synchronized void onSensorChanged(SensorEvent event) {
63 onSensorEvent(event);
64 }
65
66 @Override
67 public void onAccuracyChanged(Sensor sensor, int accuracy) {
68 }
69 };
70
Dave Mankoff84c07e92019-06-21 14:24:43 -040071 public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
72 SensorManager sensorManager) {
Dave Mankoff07fb7b72019-06-10 16:36:19 -040073 mDataProvider = falsingDataProvider;
74 mSensorManager = sensorManager;
Dave Mankoff1dee0342019-07-11 17:44:54 -040075 mMetricsLogger = new MetricsLogger();
Dave Mankoff07fb7b72019-06-10 16:36:19 -040076 mClassifiers = new ArrayList<>();
Dave Mankoff8bfbe332019-06-12 17:58:30 -040077 DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
78 ProximityClassifier proximityClassifier = new ProximityClassifier(distanceClassifier,
79 mDataProvider);
Dave Mankoff7abe1352019-06-11 11:32:52 -040080 mClassifiers.add(new PointerCountClassifier(mDataProvider));
Dave Mankofffd42bdbb2019-06-11 14:51:45 -040081 mClassifiers.add(new TypeClassifier(mDataProvider));
Dave Mankoffd8efd0d2019-06-11 16:48:34 -040082 mClassifiers.add(new DiagonalClassifier(mDataProvider));
Dave Mankoff8bfbe332019-06-12 17:58:30 -040083 mClassifiers.add(distanceClassifier);
84 mClassifiers.add(proximityClassifier);
Dave Mankoff89ad2462019-06-14 14:59:05 -040085 mClassifiers.add(new ZigZagClassifier(mDataProvider));
Dave Mankoff07fb7b72019-06-10 16:36:19 -040086 }
87
88 private void registerSensors() {
89 Sensor s = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
90 if (s != null) {
91 // This can be expensive, and doesn't need to happen on the main thread.
92 mBackgroundExecutor.submit(() -> {
93 logDebug("registering sensor listener");
94 mSensorManager.registerListener(
95 mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
96 });
97 }
98 }
99
100
101 private void unregisterSensors() {
102 // This can be expensive, and doesn't need to happen on the main thread.
103 mBackgroundExecutor.submit(() -> {
104 logDebug("unregistering sensor listener");
105 mSensorManager.unregisterListener(mSensorEventListener);
106 });
107 }
108
109 private void sessionStart() {
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400110 if (!mSessionStarted && !mShowingAod && mScreenOn) {
Dave Mankoff0ae8f2e2019-07-24 18:06:44 -0400111 logDebug("Starting Session");
112 mSessionStarted = true;
113 registerSensors();
114 mClassifiers.forEach(FalsingClassifier::onSessionStarted);
115 }
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400116 }
117
118 private void sessionEnd() {
119 if (mSessionStarted) {
120 logDebug("Ending Session");
121 mSessionStarted = false;
122 unregisterSensors();
123 mDataProvider.onSessionEnd();
124 mClassifiers.forEach(FalsingClassifier::onSessionEnded);
Dave Mankoff1dee0342019-07-11 17:44:54 -0400125 if (mIsFalseTouchCalls != 0) {
126 mMetricsLogger.histogram(FALSING_REMAIN_LOCKED, mIsFalseTouchCalls);
127 mIsFalseTouchCalls = 0;
128 }
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400129 }
130 }
131
132 private void updateInteractionType(@Classifier.InteractionType int type) {
133 logDebug("InteractionType: " + type);
134 mClassifiers.forEach((classifier) -> classifier.setInteractionType(type));
135 }
136
137 @Override
138 public boolean isClassiferEnabled() {
139 return true;
140 }
141
142 @Override
143 public boolean isFalseTouch() {
144 boolean r = mClassifiers.stream().anyMatch(falsingClassifier -> {
145 boolean result = falsingClassifier.isFalseTouch();
146 if (result) {
147 logInfo(falsingClassifier.getClass().getName() + ": true");
148 } else {
149 logDebug(falsingClassifier.getClass().getName() + ": false");
150 }
151 return result;
152 });
153
154 logDebug("Is false touch? " + r);
155
156 return r;
157 }
158
159 @Override
160 public void onTouchEvent(MotionEvent motionEvent, int width, int height) {
161 // TODO: some of these classifiers might allow us to abort early, meaning we don't have to
162 // make these calls.
163 mDataProvider.onMotionEvent(motionEvent);
164 mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent));
165 }
166
167 private void onSensorEvent(SensorEvent sensorEvent) {
168 // TODO: some of these classifiers might allow us to abort early, meaning we don't have to
169 // make these calls.
170 mClassifiers.forEach((classifier) -> classifier.onSensorEvent(sensorEvent));
171 }
172
173 @Override
174 public void onSucccessfulUnlock() {
Dave Mankoff1dee0342019-07-11 17:44:54 -0400175 if (mIsFalseTouchCalls != 0) {
176 mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls);
177 mIsFalseTouchCalls = 0;
178 }
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400179 sessionEnd();
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400180 }
181
182 @Override
183 public void onNotificationActive() {
184 }
185
186 @Override
187 public void setShowingAod(boolean showingAod) {
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400188 mShowingAod = showingAod;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400189 if (showingAod) {
190 sessionEnd();
191 } else {
192 sessionStart();
193 }
194 }
195
196 @Override
197 public void onNotificatonStartDraggingDown() {
198 updateInteractionType(Classifier.NOTIFICATION_DRAG_DOWN);
199
200 }
201
202 @Override
203 public boolean isUnlockingDisabled() {
204 return false;
205 }
206
207
208 @Override
209 public void onNotificatonStopDraggingDown() {
210 }
211
212 @Override
213 public void setNotificationExpanded() {
214 }
215
216 @Override
217 public void onQsDown() {
218 updateInteractionType(Classifier.QUICK_SETTINGS);
219 }
220
221 @Override
222 public void setQsExpanded(boolean b) {
223 }
224
225 @Override
226 public boolean shouldEnforceBouncer() {
227 return false;
228 }
229
230 @Override
231 public void onTrackingStarted(boolean secure) {
232 updateInteractionType(secure ? Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
233 }
234
235 @Override
236 public void onTrackingStopped() {
237 }
238
239 @Override
240 public void onLeftAffordanceOn() {
241 }
242
243 @Override
244 public void onCameraOn() {
245 }
246
247 @Override
248 public void onAffordanceSwipingStarted(boolean rightCorner) {
249 updateInteractionType(
250 rightCorner ? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE);
251 }
252
253 @Override
254 public void onAffordanceSwipingAborted() {
255 }
256
257 @Override
258 public void onStartExpandingFromPulse() {
259 updateInteractionType(Classifier.PULSE_EXPAND);
260 }
261
262 @Override
263 public void onExpansionFromPulseStopped() {
264 }
265
266 @Override
267 public Uri reportRejectedTouch() {
268 return null;
269 }
270
271 @Override
272 public void onScreenOnFromTouch() {
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400273 onScreenTurningOn();
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400274 }
275
276 @Override
277 public boolean isReportingEnabled() {
278 return false;
279 }
280
281 @Override
282 public void onUnlockHintStarted() {
283 }
284
285 @Override
286 public void onCameraHintStarted() {
287 }
288
289 @Override
290 public void onLeftAffordanceHintStarted() {
291 }
292
293 @Override
294 public void onScreenTurningOn() {
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400295 mScreenOn = true;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400296 sessionStart();
297 }
298
299 @Override
300 public void onScreenOff() {
Dave Mankoff1a6d9e62019-07-26 13:50:08 -0400301 mScreenOn = false;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400302 sessionEnd();
303 }
304
305
306 @Override
307 public void onNotificatonStopDismissing() {
308 }
309
310 @Override
311 public void onNotificationDismissed() {
312 }
313
314 @Override
315 public void onNotificatonStartDismissing() {
316 updateInteractionType(Classifier.NOTIFICATION_DISMISS);
317 }
318
319 @Override
320 public void onNotificationDoubleTap(boolean b, float v, float v1) {
321 }
322
323 @Override
324 public void onBouncerShown() {
325 }
326
327 @Override
328 public void onBouncerHidden() {
329 }
330
331 @Override
332 public void dump(PrintWriter printWriter) {
333 }
334
Dave Mankoff4c5a13e2019-07-16 15:07:01 -0400335 @Override
336 public void cleanup() {
337 unregisterSensors();
338 }
339
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400340 static void logDebug(String msg) {
341 logDebug(msg, null);
342 }
343
344 static void logDebug(String msg, Throwable throwable) {
345 if (DEBUG) {
346 Log.d(TAG, msg, throwable);
347 }
348 }
349
350 static void logInfo(String msg) {
351 Log.i(TAG, msg);
352 }
353
354 static void logError(String msg) {
355 Log.e(TAG, msg);
356 }
357}