blob: 937f7d3194322cbb92b5543255b623f73eceb080 [file] [log] [blame]
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07001/*
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
17package com.android.systemui.classifier;
18
19import android.content.Context;
20import android.database.ContentObserver;
21import android.hardware.Sensor;
22import android.hardware.SensorEvent;
23import android.hardware.SensorEventListener;
24import android.hardware.SensorManager;
25import android.os.Handler;
Adrian Roosc5584ce2016-02-24 14:17:19 -080026import android.os.PowerManager;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070027import android.os.UserHandle;
28import android.provider.Settings;
29import android.view.MotionEvent;
30
31import com.android.systemui.analytics.DataCollector;
32import com.android.systemui.statusbar.StatusBarState;
33
Adrian Roos401caae2016-03-04 13:35:21 -080034import java.io.PrintWriter;
35
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070036/**
37 * When the phone is locked, listens to touch, sensor and phone events and sends them to
38 * DataCollector and HumanInteractionClassifier.
39 *
40 * It does not collect touch events when the bouncer shows up.
41 */
42public class FalsingManager implements SensorEventListener {
43 private static final String ENFORCE_BOUNCER = "falsing_manager_enforce_bouncer";
44
Blazej Magnowski6dc59b42015-09-22 15:14:20 -070045 private static final int[] CLASSIFIER_SENSORS = new int[] {
46 Sensor.TYPE_PROXIMITY,
47 };
48
49 private static final int[] COLLECTOR_SENSORS = new int[] {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070050 Sensor.TYPE_ACCELEROMETER,
51 Sensor.TYPE_GYROSCOPE,
52 Sensor.TYPE_PROXIMITY,
53 Sensor.TYPE_LIGHT,
54 Sensor.TYPE_ROTATION_VECTOR,
55 };
56
57 private final Handler mHandler = new Handler();
58 private final Context mContext;
59
60 private final SensorManager mSensorManager;
61 private final DataCollector mDataCollector;
62 private final HumanInteractionClassifier mHumanInteractionClassifier;
63
64 private static FalsingManager sInstance = null;
65
66 private boolean mEnforceBouncer = false;
67 private boolean mBouncerOn = false;
68 private boolean mSessionActive = false;
69 private int mState = StatusBarState.SHADE;
Adrian Roosc5584ce2016-02-24 14:17:19 -080070 private boolean mScreenOn;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070071
72 protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
73 @Override
74 public void onChange(boolean selfChange) {
75 updateConfiguration();
76 }
77 };
78
79 private FalsingManager(Context context) {
80 mContext = context;
81 mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
82 mDataCollector = DataCollector.getInstance(mContext);
83 mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
Adrian Roosc5584ce2016-02-24 14:17:19 -080084 mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070085
86 mContext.getContentResolver().registerContentObserver(
87 Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
88 mSettingsObserver,
89 UserHandle.USER_ALL);
90
91 updateConfiguration();
92 }
93
94 public static FalsingManager getInstance(Context context) {
95 if (sInstance == null) {
96 sInstance = new FalsingManager(context);
97 }
98 return sInstance;
99 }
100
101 private void updateConfiguration() {
102 mEnforceBouncer = 0 != Settings.Secure.getInt(mContext.getContentResolver(),
103 ENFORCE_BOUNCER, 0);
104 }
105
Adrian Roosc5584ce2016-02-24 14:17:19 -0800106 private boolean shouldSessionBeActive() {
Adrian Roos401caae2016-03-04 13:35:21 -0800107 if (FalsingLog.ENABLED && FalsingLog.VERBOSE)
108 FalsingLog.v("shouldBeActive", new StringBuilder()
109 .append("enabled=").append(isEnabled() ? 1 : 0)
110 .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
111 .append(" mState=").append(StatusBarState.toShortString(mState))
112 .toString()
113 );
114 return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD);
Adrian Roosc5584ce2016-02-24 14:17:19 -0800115 }
116
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700117 private boolean sessionEntrypoint() {
Adrian Roosc5584ce2016-02-24 14:17:19 -0800118 if (!mSessionActive && shouldSessionBeActive()) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700119 onSessionStart();
120 return true;
121 }
122 return false;
123 }
124
Adrian Roosc5584ce2016-02-24 14:17:19 -0800125 private void sessionExitpoint(boolean force) {
126 if (mSessionActive && (force || !shouldSessionBeActive())) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700127 mSessionActive = false;
128 mSensorManager.unregisterListener(this);
129 }
130 }
131
132 private void onSessionStart() {
Adrian Roos401caae2016-03-04 13:35:21 -0800133 if (FalsingLog.ENABLED) {
134 FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassiferEnabled());
135 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700136 mBouncerOn = false;
137 mSessionActive = true;
Blazej Magnowski6dc59b42015-09-22 15:14:20 -0700138
139 if (mHumanInteractionClassifier.isEnabled()) {
140 registerSensors(CLASSIFIER_SENSORS);
141 }
142 if (mDataCollector.isEnabled()) {
143 registerSensors(COLLECTOR_SENSORS);
144 }
145 }
146
147 private void registerSensors(int [] sensors) {
148 for (int sensorType : sensors) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700149 Sensor s = mSensorManager.getDefaultSensor(sensorType);
150 if (s != null) {
151 mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
152 }
153 }
154 }
155
Blazej Magnowski6dc59b42015-09-22 15:14:20 -0700156 public boolean isClassiferEnabled() {
157 return mHumanInteractionClassifier.isEnabled();
158 }
159
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700160 private boolean isEnabled() {
161 return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
162 }
163
164 /**
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700165 * @return true if the classifier determined that this is not a human interacting with the phone
166 */
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700167 public boolean isFalseTouch() {
Adrian Roos401caae2016-03-04 13:35:21 -0800168 if (FalsingLog.ENABLED) {
169 if (!mSessionActive) {
170 FalsingLog.wtf("isFalseTouch", new StringBuilder()
171 .append("Session is not active, yet there's a query for a false touch.")
172 .append(" enabled=").append(isEnabled() ? 1 : 0)
173 .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
174 .append(" mState=").append(StatusBarState.toShortString(mState))
175 .toString());
176 }
177 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700178 return mHumanInteractionClassifier.isFalseTouch();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700179 }
180
181 @Override
182 public synchronized void onSensorChanged(SensorEvent event) {
183 mDataCollector.onSensorChanged(event);
184 mHumanInteractionClassifier.onSensorChanged(event);
185 }
186
187 @Override
188 public void onAccuracyChanged(Sensor sensor, int accuracy) {
189 mDataCollector.onAccuracyChanged(sensor, accuracy);
190 }
191
192 public boolean shouldEnforceBouncer() {
193 return mEnforceBouncer;
194 }
195
196 public void setStatusBarState(int state) {
Adrian Roos401caae2016-03-04 13:35:21 -0800197 if (FalsingLog.ENABLED) {
198 FalsingLog.i("setStatusBarState", new StringBuilder()
199 .append("from=").append(StatusBarState.toShortString(mState))
200 .append(" to=").append(StatusBarState.toShortString(state))
201 .toString());
202 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700203 mState = state;
Adrian Roosc5584ce2016-02-24 14:17:19 -0800204 if (shouldSessionBeActive()) {
205 sessionEntrypoint();
206 } else {
207 sessionExitpoint(false /* force */);
208 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700209 }
210
211 public void onScreenTurningOn() {
Adrian Roos401caae2016-03-04 13:35:21 -0800212 if (FalsingLog.ENABLED) {
213 FalsingLog.i("onScreenTurningOn", new StringBuilder()
214 .append("from=").append(mScreenOn ? 1 : 0)
215 .toString());
216 }
Adrian Roosc5584ce2016-02-24 14:17:19 -0800217 mScreenOn = true;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700218 if (sessionEntrypoint()) {
219 mDataCollector.onScreenTurningOn();
220 }
221 }
222
223 public void onScreenOnFromTouch() {
Adrian Roos401caae2016-03-04 13:35:21 -0800224 if (FalsingLog.ENABLED) {
225 FalsingLog.i("onScreenOnFromTouch", new StringBuilder()
226 .append("from=").append(mScreenOn ? 1 : 0)
227 .toString());
228 }
Adrian Roosc5584ce2016-02-24 14:17:19 -0800229 mScreenOn = true;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700230 if (sessionEntrypoint()) {
231 mDataCollector.onScreenOnFromTouch();
232 }
233 }
234
235 public void onScreenOff() {
Adrian Roos401caae2016-03-04 13:35:21 -0800236 if (FalsingLog.ENABLED) {
237 FalsingLog.i("onScreenOff", new StringBuilder()
238 .append("from=").append(mScreenOn ? 1 : 0)
239 .toString());
240 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700241 mDataCollector.onScreenOff();
Adrian Roosc5584ce2016-02-24 14:17:19 -0800242 mScreenOn = false;
243 sessionExitpoint(false /* force */);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700244 }
245
246 public void onSucccessfulUnlock() {
Adrian Roos401caae2016-03-04 13:35:21 -0800247 if (FalsingLog.ENABLED) {
248 FalsingLog.i("onSucccessfulUnlock", "");
249 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700250 mDataCollector.onSucccessfulUnlock();
Adrian Roosc5584ce2016-02-24 14:17:19 -0800251 sessionExitpoint(true /* force */);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700252 }
253
254 public void onBouncerShown() {
Adrian Roos401caae2016-03-04 13:35:21 -0800255 if (FalsingLog.ENABLED) {
256 FalsingLog.i("onBouncerShown", new StringBuilder()
257 .append("from=").append(mBouncerOn ? 1 : 0)
258 .toString());
259 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700260 if (!mBouncerOn) {
261 mBouncerOn = true;
262 mDataCollector.onBouncerShown();
263 }
264 }
265
266 public void onBouncerHidden() {
Adrian Roos401caae2016-03-04 13:35:21 -0800267 if (FalsingLog.ENABLED) {
268 FalsingLog.i("onBouncerHidden", new StringBuilder()
269 .append("from=").append(mBouncerOn ? 1 : 0)
270 .toString());
271 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700272 if (mBouncerOn) {
273 mBouncerOn = false;
274 mDataCollector.onBouncerHidden();
275 }
276 }
277
278 public void onQsDown() {
Adrian Roos401caae2016-03-04 13:35:21 -0800279 if (FalsingLog.ENABLED) {
280 FalsingLog.i("onQsDown", "");
281 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700282 mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700283 mDataCollector.onQsDown();
284 }
285
286 public void setQsExpanded(boolean expanded) {
287 mDataCollector.setQsExpanded(expanded);
288 }
289
290 public void onTrackingStarted() {
Adrian Roos401caae2016-03-04 13:35:21 -0800291 if (FalsingLog.ENABLED) {
292 FalsingLog.i("onTrackingStarted", "");
293 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700294 mHumanInteractionClassifier.setType(Classifier.UNLOCK);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700295 mDataCollector.onTrackingStarted();
296 }
297
298 public void onTrackingStopped() {
299 mDataCollector.onTrackingStopped();
300 }
301
302 public void onNotificationActive() {
303 mDataCollector.onNotificationActive();
304 }
305
306 public void onNotificationDoubleTap() {
307 mDataCollector.onNotificationDoubleTap();
308 }
309
310 public void setNotificationExpanded() {
311 mDataCollector.setNotificationExpanded();
312 }
313
314 public void onNotificatonStartDraggingDown() {
Adrian Roos401caae2016-03-04 13:35:21 -0800315 if (FalsingLog.ENABLED) {
316 FalsingLog.i("onNotificatonStartDraggingDown", "");
317 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700318 mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700319 mDataCollector.onNotificatonStartDraggingDown();
320 }
321
322 public void onNotificatonStopDraggingDown() {
323 mDataCollector.onNotificatonStopDraggingDown();
324 }
325
326 public void onNotificationDismissed() {
327 mDataCollector.onNotificationDismissed();
328 }
329
330 public void onNotificatonStartDismissing() {
Adrian Roos401caae2016-03-04 13:35:21 -0800331 if (FalsingLog.ENABLED) {
332 FalsingLog.i("onNotificatonStartDismissing", "");
333 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700334 mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700335 mDataCollector.onNotificatonStartDismissing();
336 }
337
338 public void onNotificatonStopDismissing() {
339 mDataCollector.onNotificatonStopDismissing();
340 }
341
342 public void onCameraOn() {
343 mDataCollector.onCameraOn();
344 }
345
346 public void onLeftAffordanceOn() {
347 mDataCollector.onLeftAffordanceOn();
348 }
349
350 public void onAffordanceSwipingStarted(boolean rightCorner) {
Adrian Roos401caae2016-03-04 13:35:21 -0800351 if (FalsingLog.ENABLED) {
352 FalsingLog.i("onAffordanceSwipingStarted", "");
353 }
Blazej Magnowski9f01c5b2015-09-17 15:14:29 -0700354 if (rightCorner) {
355 mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE);
356 } else {
357 mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE);
358 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700359 mDataCollector.onAffordanceSwipingStarted(rightCorner);
360 }
361
362 public void onAffordanceSwipingAborted() {
363 mDataCollector.onAffordanceSwipingAborted();
364 }
365
366 public void onUnlockHintStarted() {
367 mDataCollector.onUnlockHintStarted();
368 }
369
370 public void onCameraHintStarted() {
371 mDataCollector.onCameraHintStarted();
372 }
373
374 public void onLeftAffordanceHintStarted() {
375 mDataCollector.onLeftAffordanceHintStarted();
376 }
377
378 public void onTouchEvent(MotionEvent event, int width, int height) {
379 if (mSessionActive && !mBouncerOn) {
380 mDataCollector.onTouchEvent(event, width, height);
381 mHumanInteractionClassifier.onTouchEvent(event);
382 }
383 }
Adrian Roos401caae2016-03-04 13:35:21 -0800384
385 public void dump(PrintWriter pw) {
386 pw.println("FALSING MANAGER");
387 pw.print("classifierEnabled="); pw.println(isClassiferEnabled() ? 1 : 0);
388 pw.print("mSessionActive="); pw.println(mSessionActive ? 1 : 0);
389 pw.print("mBouncerOn="); pw.println(mSessionActive ? 1 : 0);
390 pw.print("mState="); pw.println(StatusBarState.toShortString(mState));
391 pw.print("mScreenOn="); pw.println(mScreenOn ? 1 : 0);
392 pw.println();
393 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700394}