1 /* 2 * Copyright (C) 2020 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 17 package com.android.systemui.classifier; 18 19 import static com.android.systemui.dock.DockManager.DockEventListener; 20 21 import android.hardware.SensorManager; 22 import android.hardware.biometrics.BiometricSourceType; 23 import android.util.Log; 24 import android.view.MotionEvent; 25 26 import androidx.annotation.VisibleForTesting; 27 28 import com.android.keyguard.KeyguardUpdateMonitor; 29 import com.android.keyguard.KeyguardUpdateMonitorCallback; 30 import com.android.systemui.dagger.SysUISingleton; 31 import com.android.systemui.dagger.qualifiers.Main; 32 import com.android.systemui.dock.DockManager; 33 import com.android.systemui.plugins.FalsingManager; 34 import com.android.systemui.plugins.statusbar.StatusBarStateController; 35 import com.android.systemui.shade.ShadeExpansionStateManager; 36 import com.android.systemui.statusbar.StatusBarState; 37 import com.android.systemui.statusbar.policy.BatteryController; 38 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 39 import com.android.systemui.statusbar.policy.KeyguardStateController; 40 import com.android.systemui.util.concurrency.DelayableExecutor; 41 import com.android.systemui.util.sensors.ProximitySensor; 42 import com.android.systemui.util.sensors.ThresholdSensor; 43 import com.android.systemui.util.sensors.ThresholdSensorEvent; 44 import com.android.systemui.util.time.SystemClock; 45 46 import java.util.Collections; 47 48 import javax.inject.Inject; 49 50 @SysUISingleton 51 class FalsingCollectorImpl implements FalsingCollector { 52 53 private static final String TAG = "FalsingCollector"; 54 private static final String PROXIMITY_SENSOR_TAG = "FalsingCollector"; 55 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 56 private static final long GESTURE_PROCESSING_DELAY_MS = 100; 57 58 private final FalsingDataProvider mFalsingDataProvider; 59 private final FalsingManager mFalsingManager; 60 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 61 private final HistoryTracker mHistoryTracker; 62 private final ProximitySensor mProximitySensor; 63 private final StatusBarStateController mStatusBarStateController; 64 private final KeyguardStateController mKeyguardStateController; 65 private final BatteryController mBatteryController; 66 private final DockManager mDockManager; 67 private final DelayableExecutor mMainExecutor; 68 private final SystemClock mSystemClock; 69 70 private int mState; 71 private boolean mShowingAod; 72 private boolean mScreenOn; 73 private boolean mSessionStarted; 74 private MotionEvent mPendingDownEvent; 75 private boolean mAvoidGesture; 76 77 private final ThresholdSensor.Listener mSensorEventListener = this::onProximityEvent; 78 79 private final StatusBarStateController.StateListener mStatusBarStateListener = 80 new StatusBarStateController.StateListener() { 81 @Override 82 public void onStateChanged(int newState) { 83 logDebug("StatusBarState=" + StatusBarState.toString(newState)); 84 mState = newState; 85 updateSessionActive(); 86 } 87 }; 88 89 90 private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = 91 new KeyguardUpdateMonitorCallback() { 92 @Override 93 public void onBiometricAuthenticated(int userId, 94 BiometricSourceType biometricSourceType, 95 boolean isStrongBiometric) { 96 if (userId == KeyguardUpdateMonitor.getCurrentUser() 97 && biometricSourceType == BiometricSourceType.FACE) { 98 mFalsingDataProvider.setJustUnlockedWithFace(true); 99 } 100 } 101 }; 102 103 104 private final BatteryStateChangeCallback mBatteryListener = new BatteryStateChangeCallback() { 105 @Override 106 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 107 } 108 109 @Override 110 public void onWirelessChargingChanged(boolean isWirelessCharging) { 111 if (isWirelessCharging || mDockManager.isDocked()) { 112 mProximitySensor.pause(); 113 } else { 114 mProximitySensor.resume(); 115 } 116 } 117 }; 118 119 private final DockEventListener mDockEventListener = new DockEventListener() { 120 @Override 121 public void onEvent(int event) { 122 if (event == DockManager.STATE_NONE && !mBatteryController.isWirelessCharging()) { 123 mProximitySensor.resume(); 124 } else { 125 mProximitySensor.pause(); 126 } 127 } 128 }; 129 130 @Inject FalsingCollectorImpl( FalsingDataProvider falsingDataProvider, FalsingManager falsingManager, KeyguardUpdateMonitor keyguardUpdateMonitor, HistoryTracker historyTracker, ProximitySensor proximitySensor, StatusBarStateController statusBarStateController, KeyguardStateController keyguardStateController, ShadeExpansionStateManager shadeExpansionStateManager, BatteryController batteryController, DockManager dockManager, @Main DelayableExecutor mainExecutor, SystemClock systemClock)131 FalsingCollectorImpl( 132 FalsingDataProvider falsingDataProvider, 133 FalsingManager falsingManager, 134 KeyguardUpdateMonitor keyguardUpdateMonitor, 135 HistoryTracker historyTracker, 136 ProximitySensor proximitySensor, 137 StatusBarStateController statusBarStateController, 138 KeyguardStateController keyguardStateController, 139 ShadeExpansionStateManager shadeExpansionStateManager, 140 BatteryController batteryController, 141 DockManager dockManager, 142 @Main DelayableExecutor mainExecutor, 143 SystemClock systemClock) { 144 mFalsingDataProvider = falsingDataProvider; 145 mFalsingManager = falsingManager; 146 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 147 mHistoryTracker = historyTracker; 148 mProximitySensor = proximitySensor; 149 mStatusBarStateController = statusBarStateController; 150 mKeyguardStateController = keyguardStateController; 151 mBatteryController = batteryController; 152 mDockManager = dockManager; 153 mMainExecutor = mainExecutor; 154 mSystemClock = systemClock; 155 156 mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); 157 mProximitySensor.setDelay(SensorManager.SENSOR_DELAY_GAME); 158 159 mStatusBarStateController.addCallback(mStatusBarStateListener); 160 mState = mStatusBarStateController.getState(); 161 162 mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); 163 164 shadeExpansionStateManager.addQsExpansionListener(this::onQsExpansionChanged); 165 166 mBatteryController.addCallback(mBatteryListener); 167 mDockManager.addListener(mDockEventListener); 168 } 169 170 @Override onSuccessfulUnlock()171 public void onSuccessfulUnlock() { 172 mFalsingManager.onSuccessfulUnlock(); 173 sessionEnd(); 174 } 175 176 @Override setShowingAod(boolean showingAod)177 public void setShowingAod(boolean showingAod) { 178 mShowingAod = showingAod; 179 updateSessionActive(); 180 } 181 182 @Override onNotificationStartDraggingDown()183 public void onNotificationStartDraggingDown() { 184 } 185 186 @Override onNotificationStopDraggingDown()187 public void onNotificationStopDraggingDown() { 188 } 189 190 @Override setNotificationExpanded()191 public void setNotificationExpanded() { 192 } 193 194 @Override onQsDown()195 public void onQsDown() { 196 } 197 198 @VisibleForTesting onQsExpansionChanged(Boolean expanded)199 void onQsExpansionChanged(Boolean expanded) { 200 if (expanded) { 201 unregisterSensors(); 202 } else if (mSessionStarted) { 203 registerSensors(); 204 } 205 } 206 207 @Override shouldEnforceBouncer()208 public boolean shouldEnforceBouncer() { 209 return false; 210 } 211 212 @Override onTrackingStarted(boolean secure)213 public void onTrackingStarted(boolean secure) { 214 } 215 216 @Override onTrackingStopped()217 public void onTrackingStopped() { 218 } 219 220 @Override onLeftAffordanceOn()221 public void onLeftAffordanceOn() { 222 } 223 224 @Override onCameraOn()225 public void onCameraOn() { 226 } 227 228 @Override onAffordanceSwipingStarted(boolean rightCorner)229 public void onAffordanceSwipingStarted(boolean rightCorner) { 230 } 231 232 @Override onAffordanceSwipingAborted()233 public void onAffordanceSwipingAborted() { 234 } 235 236 @Override onStartExpandingFromPulse()237 public void onStartExpandingFromPulse() { 238 } 239 240 @Override onExpansionFromPulseStopped()241 public void onExpansionFromPulseStopped() { 242 } 243 244 @Override onScreenOnFromTouch()245 public void onScreenOnFromTouch() { 246 onScreenTurningOn(); 247 } 248 249 @Override isReportingEnabled()250 public boolean isReportingEnabled() { 251 return false; 252 } 253 254 @Override onUnlockHintStarted()255 public void onUnlockHintStarted() { 256 } 257 258 @Override onCameraHintStarted()259 public void onCameraHintStarted() { 260 } 261 262 @Override onLeftAffordanceHintStarted()263 public void onLeftAffordanceHintStarted() { 264 } 265 266 @Override onScreenTurningOn()267 public void onScreenTurningOn() { 268 mScreenOn = true; 269 updateSessionActive(); 270 } 271 272 @Override onScreenOff()273 public void onScreenOff() { 274 mScreenOn = false; 275 updateSessionActive(); 276 } 277 278 @Override onNotificationStopDismissing()279 public void onNotificationStopDismissing() { 280 } 281 282 @Override onNotificationDismissed()283 public void onNotificationDismissed() { 284 } 285 286 @Override onNotificationStartDismissing()287 public void onNotificationStartDismissing() { 288 } 289 290 @Override onNotificationDoubleTap(boolean accepted, float dx, float dy)291 public void onNotificationDoubleTap(boolean accepted, float dx, float dy) { 292 } 293 294 @Override onBouncerShown()295 public void onBouncerShown() { 296 unregisterSensors(); 297 } 298 299 @Override onBouncerHidden()300 public void onBouncerHidden() { 301 if (mSessionStarted) { 302 registerSensors(); 303 } 304 } 305 306 @Override onTouchEvent(MotionEvent ev)307 public void onTouchEvent(MotionEvent ev) { 308 if (!mKeyguardStateController.isShowing()) { 309 avoidGesture(); 310 return; 311 } 312 if (ev.getActionMasked() == MotionEvent.ACTION_OUTSIDE) { 313 return; 314 } 315 316 // We delay processing down events to see if another component wants to process them. 317 // If #avoidGesture is called after a MotionEvent.ACTION_DOWN, all following motion events 318 // will be ignored by the collector until another MotionEvent.ACTION_DOWN is passed in. 319 // avoidGesture must be called immediately following the MotionEvent.ACTION_DOWN, before 320 // any other events are processed, otherwise the whole gesture will be recorded. 321 if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { 322 // Make a copy of ev, since it will be recycled after we exit this method. 323 mPendingDownEvent = MotionEvent.obtain(ev); 324 mAvoidGesture = false; 325 } else if (!mAvoidGesture) { 326 if (mPendingDownEvent != null) { 327 mFalsingDataProvider.onMotionEvent(mPendingDownEvent); 328 mPendingDownEvent.recycle(); 329 mPendingDownEvent = null; 330 } 331 mFalsingDataProvider.onMotionEvent(ev); 332 } 333 } 334 335 @Override onMotionEventComplete()336 public void onMotionEventComplete() { 337 // We must delay processing the completion because of the way Android handles click events. 338 // It generally delays executing them immediately, instead choosing to give the UI a chance 339 // to respond to touch events before acknowledging the click. As such, we must also delay, 340 // giving click handlers a chance to analyze it. 341 // You might think we could do something clever to remove this delay - adding non-committed 342 // results that can later be changed - but this won't help. Calling the code 343 // below can eventually end up in a "Falsing Event" being fired. If we remove the delay 344 // here, we would still have to add the delay to the event, but we'd also have to make all 345 // the intervening code more complicated in the process. This is the simplest insertion 346 // point for the delay. 347 mMainExecutor.executeDelayed( 348 mFalsingDataProvider::onMotionEventComplete, GESTURE_PROCESSING_DELAY_MS); 349 } 350 351 @Override avoidGesture()352 public void avoidGesture() { 353 mAvoidGesture = true; 354 if (mPendingDownEvent != null) { 355 mPendingDownEvent.recycle(); 356 mPendingDownEvent = null; 357 } 358 } 359 360 @Override cleanup()361 public void cleanup() { 362 unregisterSensors(); 363 mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback); 364 mStatusBarStateController.removeCallback(mStatusBarStateListener); 365 mBatteryController.removeCallback(mBatteryListener); 366 mDockManager.removeListener(mDockEventListener); 367 } 368 369 @Override updateFalseConfidence(FalsingClassifier.Result result)370 public void updateFalseConfidence(FalsingClassifier.Result result) { 371 mHistoryTracker.addResults(Collections.singleton(result), mSystemClock.uptimeMillis()); 372 } 373 374 @Override onA11yAction()375 public void onA11yAction() { 376 if (mPendingDownEvent != null) { 377 mPendingDownEvent.recycle(); 378 mPendingDownEvent = null; 379 } 380 mFalsingDataProvider.onA11yAction(); 381 } 382 shouldSessionBeActive()383 private boolean shouldSessionBeActive() { 384 return mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod; 385 } 386 updateSessionActive()387 private void updateSessionActive() { 388 if (shouldSessionBeActive()) { 389 sessionStart(); 390 } else { 391 sessionEnd(); 392 } 393 } 394 sessionStart()395 private void sessionStart() { 396 if (!mSessionStarted && shouldSessionBeActive()) { 397 logDebug("Starting Session"); 398 mSessionStarted = true; 399 mFalsingDataProvider.setJustUnlockedWithFace(false); 400 registerSensors(); 401 mFalsingDataProvider.onSessionStarted(); 402 } 403 } 404 sessionEnd()405 private void sessionEnd() { 406 if (mSessionStarted) { 407 logDebug("Ending Session"); 408 mSessionStarted = false; 409 unregisterSensors(); 410 mFalsingDataProvider.onSessionEnd(); 411 } 412 } 413 registerSensors()414 private void registerSensors() { 415 mProximitySensor.register(mSensorEventListener); 416 } 417 unregisterSensors()418 private void unregisterSensors() { 419 mProximitySensor.unregister(mSensorEventListener); 420 } 421 onProximityEvent(ThresholdSensorEvent proximityEvent)422 private void onProximityEvent(ThresholdSensorEvent proximityEvent) { 423 // TODO: some of these classifiers might allow us to abort early, meaning we don't have to 424 // make these calls. 425 mFalsingManager.onProximityEvent(new ProximityEventImpl(proximityEvent)); 426 } 427 428 logDebug(String msg)429 static void logDebug(String msg) { 430 logDebug(msg, null); 431 } 432 logDebug(String msg, Throwable throwable)433 static void logDebug(String msg, Throwable throwable) { 434 if (DEBUG) { 435 Log.d(TAG, msg, throwable); 436 } 437 } 438 439 private static class ProximityEventImpl implements FalsingManager.ProximityEvent { 440 private ThresholdSensorEvent mThresholdSensorEvent; 441 ProximityEventImpl(ThresholdSensorEvent thresholdSensorEvent)442 ProximityEventImpl(ThresholdSensorEvent thresholdSensorEvent) { 443 mThresholdSensorEvent = thresholdSensorEvent; 444 } 445 @Override getCovered()446 public boolean getCovered() { 447 return mThresholdSensorEvent.getBelow(); 448 } 449 450 @Override getTimestampNs()451 public long getTimestampNs() { 452 return mThresholdSensorEvent.getTimestampNs(); 453 } 454 } 455 } 456