• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
51 @Inject
52 constructor(
53     private val falsingManager: FalsingManager,
54     private val dockManager: DockManager,
55     private val powerInteractor: PowerInteractor,
56     private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
57     private val statusBarStateController: StatusBarStateController,
58     private val shadeLogger: ShadeLogger,
59     private val dozeInteractor: DozeInteractor,
60     userTracker: UserTracker,
61     tunerService: TunerService,
62     dumpManager: DumpManager
63 ) : GestureDetector.SimpleOnGestureListener(), Dumpable {
64     private var doubleTapEnabled = false
65     private var singleTapEnabled = false
66 
67     init {
68         val tunable = Tunable { key: String?, _: String? ->
69             when (key) {
70                 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE ->
71                     doubleTapEnabled =
72                         ambientDisplayConfiguration.doubleTapGestureEnabled(userTracker.userId)
73                 Settings.Secure.DOZE_TAP_SCREEN_GESTURE ->
74                     singleTapEnabled =
75                         ambientDisplayConfiguration.tapGestureEnabled(userTracker.userId)
76             }
77         }
78         tunerService.addTunable(
79             tunable,
80             Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
81             Settings.Secure.DOZE_TAP_SCREEN_GESTURE
82         )
83 
84         dumpManager.registerDumpable(this)
85     }
86 
87     override fun onSingleTapUp(e: MotionEvent): Boolean {
88         return onSingleTapUp(e.x, e.y)
89     }
90 
91     fun onSingleTapUp(x: Float, y: Float): Boolean {
92         val isNotDocked = !dockManager.isDocked
93         shadeLogger.logSingleTapUp(statusBarStateController.isDozing, singleTapEnabled, isNotDocked)
94         if (statusBarStateController.isDozing && singleTapEnabled && isNotDocked) {
95             val proximityIsNotNear = !falsingManager.isProximityNear
96             val isNotAFalseTap = !falsingManager.isFalseTap(LOW_PENALTY)
97             shadeLogger.logSingleTapUpFalsingState(proximityIsNotNear, isNotAFalseTap)
98             if (proximityIsNotNear && isNotAFalseTap) {
99                 shadeLogger.d("Single tap handled, requesting centralSurfaces.wakeUpIfDozing")
100                 dozeInteractor.setLastTapToWakePosition(Point(x.toInt(), y.toInt()))
101                 powerInteractor.wakeUpIfDozing("PULSING_SINGLE_TAP", PowerManager.WAKE_REASON_TAP)
102             }
103 
104             return true
105         }
106 
107         shadeLogger.d("onSingleTapUp event ignored")
108         return false
109     }
110 
111     /**
112      * Receives [MotionEvent.ACTION_DOWN], [MotionEvent.ACTION_MOVE], and [MotionEvent.ACTION_UP]
113      * motion events for a double tap.
114      */
115     override fun onDoubleTapEvent(e: MotionEvent): Boolean {
116         if (e.actionMasked != MotionEvent.ACTION_UP) {
117             return false
118         }
119 
120         return onDoubleTapEvent()
121     }
122 
123     fun onDoubleTapEvent(): Boolean {
124         // React to the [MotionEvent.ACTION_UP] event after double tap is detected. Falsing
125         // checks MUST be on the ACTION_UP event.
126         if (
127             statusBarStateController.isDozing &&
128                 (doubleTapEnabled || singleTapEnabled) &&
129                 !falsingManager.isProximityNear &&
130                 !falsingManager.isFalseDoubleTap
131         ) {
132             powerInteractor.wakeUpIfDozing("PULSING_DOUBLE_TAP", PowerManager.WAKE_REASON_TAP)
133             return true
134         }
135 
136         return false
137     }
138 
139     override fun dump(pw: PrintWriter, args: Array<out String>) {
140         pw.println("singleTapEnabled=$singleTapEnabled")
141         pw.println("doubleTapEnabled=$doubleTapEnabled")
142         pw.println("isDocked=${dockManager.isDocked}")
143         pw.println("isProxCovered=${falsingManager.isProximityNear}")
144     }
145 }
146