1 /* <lambda>null2 * Copyright (C) 2022 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.shade 18 19 import android.graphics.Point 20 import android.hardware.display.AmbientDisplayConfiguration 21 import android.os.PowerManager 22 import android.provider.Settings 23 import android.view.GestureDetector 24 import android.view.MotionEvent 25 import com.android.systemui.Dumpable 26 import com.android.systemui.dagger.SysUISingleton 27 import com.android.systemui.dock.DockManager 28 import com.android.systemui.dump.DumpManager 29 import com.android.systemui.keyguard.domain.interactor.DozeInteractor 30 import com.android.systemui.plugins.FalsingManager 31 import com.android.systemui.plugins.FalsingManager.LOW_PENALTY 32 import com.android.systemui.plugins.statusbar.StatusBarStateController 33 import com.android.systemui.power.domain.interactor.PowerInteractor 34 import com.android.systemui.settings.UserTracker 35 import com.android.systemui.tuner.TunerService 36 import com.android.systemui.tuner.TunerService.Tunable 37 import java.io.PrintWriter 38 import javax.inject.Inject 39 40 /** 41 * If tap and/or double tap to wake is enabled, this gestureListener will wake the display on 42 * tap/double tap when the device is pulsing (AoD2) or transitioning to AoD. Taps are gated by the 43 * proximity sensor and falsing manager. 44 * 45 * Touches go through the [NotificationShadeWindowViewController] when the device is dozing but the 46 * screen is still ON and not in the true AoD display state. When the device is in the true AoD 47 * display state, wake-ups are handled by [com.android.systemui.doze.DozeSensors]. 48 */ 49 @SysUISingleton 50 class PulsingGestureListener @Inject constructor( 51 private val falsingManager: FalsingManager, 52 private val dockManager: DockManager, 53 private val powerInteractor: PowerInteractor, 54 private val ambientDisplayConfiguration: AmbientDisplayConfiguration, 55 private val statusBarStateController: StatusBarStateController, 56 private val shadeLogger: ShadeLogger, 57 private val dozeInteractor: DozeInteractor, 58 userTracker: UserTracker, 59 tunerService: TunerService, 60 dumpManager: DumpManager 61 ) : GestureDetector.SimpleOnGestureListener(), Dumpable { 62 private var doubleTapEnabled = false 63 private var singleTapEnabled = false 64 65 init { 66 val tunable = Tunable { key: String?, _: String? -> 67 when (key) { 68 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE -> 69 doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled( 70 userTracker.userId) 71 Settings.Secure.DOZE_TAP_SCREEN_GESTURE -> 72 singleTapEnabled = ambientDisplayConfiguration.tapGestureEnabled( 73 userTracker.userId) 74 } 75 } 76 tunerService.addTunable(tunable, 77 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, 78 Settings.Secure.DOZE_TAP_SCREEN_GESTURE) 79 80 dumpManager.registerDumpable(this) 81 } 82 83 override fun onSingleTapUp(e: MotionEvent): Boolean { 84 val isNotDocked = !dockManager.isDocked 85 shadeLogger.logSingleTapUp(statusBarStateController.isDozing, singleTapEnabled, isNotDocked) 86 if (statusBarStateController.isDozing && singleTapEnabled && isNotDocked) { 87 val proximityIsNotNear = !falsingManager.isProximityNear 88 val isNotAFalseTap = !falsingManager.isFalseTap(LOW_PENALTY) 89 shadeLogger.logSingleTapUpFalsingState(proximityIsNotNear, isNotAFalseTap) 90 if (proximityIsNotNear && isNotAFalseTap) { 91 shadeLogger.d("Single tap handled, requesting centralSurfaces.wakeUpIfDozing") 92 dozeInteractor.setLastTapToWakePosition(Point(e.x.toInt(), e.y.toInt())) 93 powerInteractor.wakeUpIfDozing("PULSING_SINGLE_TAP", PowerManager.WAKE_REASON_TAP) 94 } 95 return true 96 } 97 shadeLogger.d("onSingleTapUp event ignored") 98 return false 99 } 100 101 /** 102 * Receives [MotionEvent.ACTION_DOWN], [MotionEvent.ACTION_MOVE], and [MotionEvent.ACTION_UP] 103 * motion events for a double tap. 104 */ 105 override fun onDoubleTapEvent(e: MotionEvent): Boolean { 106 // React to the [MotionEvent.ACTION_UP] event after double tap is detected. Falsing 107 // checks MUST be on the ACTION_UP event. 108 if (e.actionMasked == MotionEvent.ACTION_UP && 109 statusBarStateController.isDozing && 110 (doubleTapEnabled || singleTapEnabled) && 111 !falsingManager.isProximityNear && 112 !falsingManager.isFalseDoubleTap 113 ) { 114 powerInteractor.wakeUpIfDozing("PULSING_DOUBLE_TAP", PowerManager.WAKE_REASON_TAP) 115 return true 116 } 117 return false 118 } 119 120 override fun dump(pw: PrintWriter, args: Array<out String>) { 121 pw.println("singleTapEnabled=$singleTapEnabled") 122 pw.println("doubleTapEnabled=$doubleTapEnabled") 123 pw.println("isDocked=${dockManager.isDocked}") 124 pw.println("isProxCovered=${falsingManager.isProximityNear}") 125 } 126 } 127