blob: 9e0b7025ddf8c0c1e6da69966f82152c46f9bdca [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;
Dave Mankoffd61f01b2019-08-09 17:58:56 -040026import android.hardware.biometrics.BiometricSourceType;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040027import android.net.Uri;
28import android.util.Log;
29import android.view.MotionEvent;
30
Dave Mankoff1dee0342019-07-11 17:44:54 -040031import com.android.internal.logging.MetricsLogger;
Dave Mankoffd61f01b2019-08-09 17:58:56 -040032import com.android.keyguard.KeyguardUpdateMonitor;
33import com.android.keyguard.KeyguardUpdateMonitorCallback;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040034import com.android.systemui.classifier.Classifier;
35import com.android.systemui.plugins.FalsingManager;
36
37import java.io.PrintWriter;
38import java.util.ArrayList;
39import java.util.List;
40import java.util.concurrent.ExecutorService;
41import java.util.concurrent.Executors;
42
43/**
44 * FalsingManager designed to make clear why a touch was rejected.
45 */
46public class BrightLineFalsingManager implements FalsingManager {
47
48 static final boolean DEBUG = false;
49 private static final String TAG = "FalsingManagerPlugin";
50
51 private final SensorManager mSensorManager;
52 private final FalsingDataProvider mDataProvider;
Dave Mankoffd61f01b2019-08-09 17:58:56 -040053 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040054 private boolean mSessionStarted;
Dave Mankoff1dee0342019-07-11 17:44:54 -040055 private MetricsLogger mMetricsLogger;
56 private int mIsFalseTouchCalls;
Dave Mankoff622eeaf2019-07-26 13:50:08 -040057 private boolean mShowingAod;
58 private boolean mScreenOn;
Dave Mankoffd61f01b2019-08-09 17:58:56 -040059 private boolean mJustUnlockedWithFace;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040060
61 private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
62
63 private final List<FalsingClassifier> mClassifiers;
64
65 private SensorEventListener mSensorEventListener = new SensorEventListener() {
66 @Override
67 public synchronized void onSensorChanged(SensorEvent event) {
68 onSensorEvent(event);
69 }
70
71 @Override
72 public void onAccuracyChanged(Sensor sensor, int accuracy) {
73 }
74 };
75
Dave Mankoffd61f01b2019-08-09 17:58:56 -040076 private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
77 new KeyguardUpdateMonitorCallback() {
78 @Override
79 public void onBiometricAuthenticated(int userId,
80 BiometricSourceType biometricSourceType) {
81 if (userId == KeyguardUpdateMonitor.getCurrentUser()
82 && biometricSourceType == BiometricSourceType.FACE) {
83 mJustUnlockedWithFace = true;
84 }
85 }
86 };
87
88 public BrightLineFalsingManager(
89 FalsingDataProvider falsingDataProvider,
90 SensorManager sensorManager,
91 KeyguardUpdateMonitor keyguardUpdateMonitor) {
92 mKeyguardUpdateMonitor = keyguardUpdateMonitor;
Dave Mankoff07fb7b72019-06-10 16:36:19 -040093 mDataProvider = falsingDataProvider;
94 mSensorManager = sensorManager;
Dave Mankoffd61f01b2019-08-09 17:58:56 -040095 mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
96
Dave Mankoff1dee0342019-07-11 17:44:54 -040097 mMetricsLogger = new MetricsLogger();
Dave Mankoff07fb7b72019-06-10 16:36:19 -040098 mClassifiers = new ArrayList<>();
Dave Mankoff8bfbe332019-06-12 17:58:30 -040099 DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
100 ProximityClassifier proximityClassifier = new ProximityClassifier(distanceClassifier,
101 mDataProvider);
Dave Mankoff7abe1352019-06-11 11:32:52 -0400102 mClassifiers.add(new PointerCountClassifier(mDataProvider));
Dave Mankofffd42bdbb2019-06-11 14:51:45 -0400103 mClassifiers.add(new TypeClassifier(mDataProvider));
Dave Mankoffd8efd0d2019-06-11 16:48:34 -0400104 mClassifiers.add(new DiagonalClassifier(mDataProvider));
Dave Mankoff8bfbe332019-06-12 17:58:30 -0400105 mClassifiers.add(distanceClassifier);
106 mClassifiers.add(proximityClassifier);
Dave Mankoff89ad2462019-06-14 14:59:05 -0400107 mClassifiers.add(new ZigZagClassifier(mDataProvider));
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400108 }
109
110 private void registerSensors() {
111 Sensor s = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
112 if (s != null) {
113 // This can be expensive, and doesn't need to happen on the main thread.
114 mBackgroundExecutor.submit(() -> {
115 logDebug("registering sensor listener");
116 mSensorManager.registerListener(
117 mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
118 });
119 }
120 }
121
122
123 private void unregisterSensors() {
124 // This can be expensive, and doesn't need to happen on the main thread.
125 mBackgroundExecutor.submit(() -> {
126 logDebug("unregistering sensor listener");
127 mSensorManager.unregisterListener(mSensorEventListener);
128 });
129 }
130
131 private void sessionStart() {
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400132 if (!mSessionStarted && !mShowingAod && mScreenOn) {
Dave Mankoff0ae8f2e2019-07-24 18:06:44 -0400133 logDebug("Starting Session");
134 mSessionStarted = true;
Dave Mankoffd61f01b2019-08-09 17:58:56 -0400135 mJustUnlockedWithFace = false;
Dave Mankoff0ae8f2e2019-07-24 18:06:44 -0400136 registerSensors();
137 mClassifiers.forEach(FalsingClassifier::onSessionStarted);
138 }
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400139 }
140
141 private void sessionEnd() {
142 if (mSessionStarted) {
143 logDebug("Ending Session");
144 mSessionStarted = false;
145 unregisterSensors();
146 mDataProvider.onSessionEnd();
147 mClassifiers.forEach(FalsingClassifier::onSessionEnded);
Dave Mankoff1dee0342019-07-11 17:44:54 -0400148 if (mIsFalseTouchCalls != 0) {
149 mMetricsLogger.histogram(FALSING_REMAIN_LOCKED, mIsFalseTouchCalls);
150 mIsFalseTouchCalls = 0;
151 }
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400152 }
153 }
154
155 private void updateInteractionType(@Classifier.InteractionType int type) {
156 logDebug("InteractionType: " + type);
157 mClassifiers.forEach((classifier) -> classifier.setInteractionType(type));
158 }
159
160 @Override
161 public boolean isClassiferEnabled() {
162 return true;
163 }
164
165 @Override
166 public boolean isFalseTouch() {
Dave Mankoffd61f01b2019-08-09 17:58:56 -0400167 boolean r = !mJustUnlockedWithFace && mClassifiers.stream().anyMatch(falsingClassifier -> {
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400168 boolean result = falsingClassifier.isFalseTouch();
169 if (result) {
170 logInfo(falsingClassifier.getClass().getName() + ": true");
171 } else {
172 logDebug(falsingClassifier.getClass().getName() + ": false");
173 }
174 return result;
175 });
176
177 logDebug("Is false touch? " + r);
178
179 return r;
180 }
181
182 @Override
183 public void onTouchEvent(MotionEvent motionEvent, int width, int height) {
184 // TODO: some of these classifiers might allow us to abort early, meaning we don't have to
185 // make these calls.
186 mDataProvider.onMotionEvent(motionEvent);
187 mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent));
188 }
189
190 private void onSensorEvent(SensorEvent sensorEvent) {
191 // TODO: some of these classifiers might allow us to abort early, meaning we don't have to
192 // make these calls.
193 mClassifiers.forEach((classifier) -> classifier.onSensorEvent(sensorEvent));
194 }
195
196 @Override
197 public void onSucccessfulUnlock() {
Dave Mankoff1dee0342019-07-11 17:44:54 -0400198 if (mIsFalseTouchCalls != 0) {
199 mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls);
200 mIsFalseTouchCalls = 0;
201 }
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400202 sessionEnd();
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400203 }
204
205 @Override
206 public void onNotificationActive() {
207 }
208
209 @Override
210 public void setShowingAod(boolean showingAod) {
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400211 mShowingAod = showingAod;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400212 if (showingAod) {
213 sessionEnd();
214 } else {
215 sessionStart();
216 }
217 }
218
219 @Override
220 public void onNotificatonStartDraggingDown() {
221 updateInteractionType(Classifier.NOTIFICATION_DRAG_DOWN);
222
223 }
224
225 @Override
226 public boolean isUnlockingDisabled() {
227 return false;
228 }
229
230
231 @Override
232 public void onNotificatonStopDraggingDown() {
233 }
234
235 @Override
236 public void setNotificationExpanded() {
237 }
238
239 @Override
240 public void onQsDown() {
241 updateInteractionType(Classifier.QUICK_SETTINGS);
242 }
243
244 @Override
245 public void setQsExpanded(boolean b) {
246 }
247
248 @Override
249 public boolean shouldEnforceBouncer() {
250 return false;
251 }
252
253 @Override
254 public void onTrackingStarted(boolean secure) {
255 updateInteractionType(secure ? Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
256 }
257
258 @Override
259 public void onTrackingStopped() {
260 }
261
262 @Override
263 public void onLeftAffordanceOn() {
264 }
265
266 @Override
267 public void onCameraOn() {
268 }
269
270 @Override
271 public void onAffordanceSwipingStarted(boolean rightCorner) {
272 updateInteractionType(
273 rightCorner ? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE);
274 }
275
276 @Override
277 public void onAffordanceSwipingAborted() {
278 }
279
280 @Override
281 public void onStartExpandingFromPulse() {
282 updateInteractionType(Classifier.PULSE_EXPAND);
283 }
284
285 @Override
286 public void onExpansionFromPulseStopped() {
287 }
288
289 @Override
290 public Uri reportRejectedTouch() {
291 return null;
292 }
293
294 @Override
295 public void onScreenOnFromTouch() {
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400296 onScreenTurningOn();
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400297 }
298
299 @Override
300 public boolean isReportingEnabled() {
301 return false;
302 }
303
304 @Override
305 public void onUnlockHintStarted() {
306 }
307
308 @Override
309 public void onCameraHintStarted() {
310 }
311
312 @Override
313 public void onLeftAffordanceHintStarted() {
314 }
315
316 @Override
317 public void onScreenTurningOn() {
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400318 mScreenOn = true;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400319 sessionStart();
320 }
321
322 @Override
323 public void onScreenOff() {
Dave Mankoff622eeaf2019-07-26 13:50:08 -0400324 mScreenOn = false;
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400325 sessionEnd();
326 }
327
328
329 @Override
330 public void onNotificatonStopDismissing() {
331 }
332
333 @Override
334 public void onNotificationDismissed() {
335 }
336
337 @Override
338 public void onNotificatonStartDismissing() {
339 updateInteractionType(Classifier.NOTIFICATION_DISMISS);
340 }
341
342 @Override
343 public void onNotificationDoubleTap(boolean b, float v, float v1) {
344 }
345
346 @Override
347 public void onBouncerShown() {
348 }
349
350 @Override
351 public void onBouncerHidden() {
352 }
353
354 @Override
355 public void dump(PrintWriter printWriter) {
356 }
357
Dave Mankoff4c5a13e2019-07-16 15:07:01 -0400358 @Override
359 public void cleanup() {
360 unregisterSensors();
Dave Mankoffd61f01b2019-08-09 17:58:56 -0400361 mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
Dave Mankoff4c5a13e2019-07-16 15:07:01 -0400362 }
363
Dave Mankoff07fb7b72019-06-10 16:36:19 -0400364 static void logDebug(String msg) {
365 logDebug(msg, null);
366 }
367
368 static void logDebug(String msg, Throwable throwable) {
369 if (DEBUG) {
370 Log.d(TAG, msg, throwable);
371 }
372 }
373
374 static void logInfo(String msg) {
375 Log.i(TAG, msg);
376 }
377
378 static void logError(String msg) {
379 Log.e(TAG, msg);
380 }
381}