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