Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import androidx.annotation.VisibleForTesting import com.android.internal.widget.CachingIconView import com.android.internal.widget.CachingIconView import com.android.systemui.R import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor /** /** Loading @@ -42,6 +43,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( internal val context: Context, internal val context: Context, private val windowManager: WindowManager, private val windowManager: WindowManager, @Main private val mainExecutor: DelayableExecutor, @Main private val mainExecutor: DelayableExecutor, private val tapGestureDetector: TapGestureDetector, @LayoutRes private val chipLayoutRes: Int @LayoutRes private val chipLayoutRes: Int ) { ) { /** The window layout parameters we'll use when attaching the view to a window. */ /** The window layout parameters we'll use when attaching the view to a window. */ Loading Loading @@ -82,6 +84,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // Add view if necessary // Add view if necessary if (oldChipView == null) { if (oldChipView == null) { tapGestureDetector.addOnGestureDetectedCallback(TAG, this::removeChip) windowManager.addView(chipView, windowLayoutParams) windowManager.addView(chipView, windowLayoutParams) } } Loading @@ -96,6 +99,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // TransferTriggered state: Once the user has initiated the transfer, they should be able // TransferTriggered state: Once the user has initiated the transfer, they should be able // to move away from the receiver device but still see the status of the transfer. // to move away from the receiver device but still see the status of the transfer. if (chipView == null) { return } if (chipView == null) { return } tapGestureDetector.removeOnGestureDetectedCallback(TAG) windowManager.removeView(chipView) windowManager.removeView(chipView) chipView = null chipView = null } } Loading Loading @@ -128,5 +132,6 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and // UpdateMediaTapToTransferReceiverDisplayTest // UpdateMediaTapToTransferReceiverDisplayTest private const val WINDOW_TITLE = "Media Transfer Chip View" private const val WINDOW_TITLE = "Media Transfer Chip View" private val TAG = MediaTttChipControllerCommon::class.simpleName!! @VisibleForTesting @VisibleForTesting const val TIMEOUT_MILLIS = 3000L const val TIMEOUT_MILLIS = 3000L packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor import javax.inject.Inject import javax.inject.Inject Loading @@ -43,9 +44,10 @@ class MediaTttChipControllerReceiver @Inject constructor( context: Context, context: Context, windowManager: WindowManager, windowManager: WindowManager, mainExecutor: DelayableExecutor, mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, @Main private val mainHandler: Handler, @Main private val mainHandler: Handler, ) : MediaTttChipControllerCommon<ChipStateReceiver>( ) : MediaTttChipControllerCommon<ChipStateReceiver>( context, windowManager, mainExecutor, R.layout.media_ttt_chip_receiver context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip_receiver ) { ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferReceiverDisplay( override fun updateMediaTapToTransferReceiverDisplay( Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor import javax.inject.Inject import javax.inject.Inject Loading @@ -42,9 +43,10 @@ class MediaTttChipControllerSender @Inject constructor( commandQueue: CommandQueue, commandQueue: CommandQueue, context: Context, context: Context, windowManager: WindowManager, windowManager: WindowManager, @Main private val mainExecutor: DelayableExecutor, @Main mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, ) : MediaTttChipControllerCommon<ChipStateSender>( ) : MediaTttChipControllerCommon<ChipStateSender>( context, windowManager, mainExecutor, R.layout.media_ttt_chip context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip ) { ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferSenderDisplay( override fun updateMediaTapToTransferSenderDisplay( Loading packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt 0 → 100644 +102 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.statusbar.gesture import android.annotation.CallSuper import android.os.Looper import android.view.Choreographer import android.view.Display import android.view.InputEvent import com.android.systemui.shared.system.InputChannelCompat import com.android.systemui.shared.system.InputMonitorCompat /** * An abstract class to help detect gestures that occur anywhere on the display (not specific to a * certain view). * * This class handles starting/stopping the gesture detection system as well as * registering/unregistering callbacks for when gestures occur. Note that the class will only listen * for gestures when there's at least one callback registered. * * Subclasses should implement [onInputEvent] to detect their specific gesture. Once a specific * gesture is detected, they should call [onGestureDetected] (which will notify the callbacks). */ abstract class GenericGestureDetector( private val tag: String ) { /** * Active callbacks, each associated with a tag. Gestures will only be monitored if * [callbacks.size] > 0. */ private val callbacks: MutableMap<String, () -> Unit> = mutableMapOf() private var inputMonitor: InputMonitorCompat? = null private var inputReceiver: InputChannelCompat.InputEventReceiver? = null /** Adds a callback that will be triggered when the tap gesture is detected. */ fun addOnGestureDetectedCallback(tag: String, callback: () -> Unit) { val callbacksWasEmpty = callbacks.isEmpty() callbacks[tag] = callback if (callbacksWasEmpty) { startGestureListening() } } /** Removes the callback. */ fun removeOnGestureDetectedCallback(tag: String) { callbacks.remove(tag) if (callbacks.isEmpty()) { stopGestureListening() } } /** Triggered each time a touch event occurs (and at least one callback is registered). */ abstract fun onInputEvent(ev: InputEvent) /** Should be called by subclasses when their specific gesture is detected. */ internal fun onGestureDetected() { callbacks.values.forEach { it.invoke() } } /** Start listening to touch events. */ @CallSuper internal open fun startGestureListening() { stopGestureListening() inputMonitor = InputMonitorCompat(tag, Display.DEFAULT_DISPLAY).also { inputReceiver = it.getInputReceiver( Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent ) } } /** Stop listening to touch events. */ @CallSuper internal open fun stopGestureListening() { inputMonitor?.let { inputMonitor = null it.dispose() } inputReceiver?.let { inputReceiver = null it.dispose() } } } packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt +12 −58 Original line number Original line Diff line number Diff line Loading @@ -17,15 +17,13 @@ package com.android.systemui.statusbar.gesture package com.android.systemui.statusbar.gesture import android.content.Context import android.content.Context import android.os.Looper import android.view.Choreographer import android.view.Display import android.view.InputEvent import android.view.InputEvent import android.view.MotionEvent import android.view.MotionEvent import android.view.MotionEvent.* import android.view.MotionEvent.ACTION_CANCEL import android.view.MotionEvent.ACTION_DOWN import android.view.MotionEvent.ACTION_MOVE import android.view.MotionEvent.ACTION_UP import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shared.system.InputChannelCompat import com.android.systemui.shared.system.InputMonitorCompat import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.statusbar.window.StatusBarWindowController import javax.inject.Inject import javax.inject.Inject Loading @@ -38,43 +36,17 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( context: Context, context: Context, private val statusBarWindowController: StatusBarWindowController, private val statusBarWindowController: StatusBarWindowController, private val logger: SwipeStatusBarAwayGestureLogger private val logger: SwipeStatusBarAwayGestureLogger ) { ) : GenericGestureDetector(SwipeStatusBarAwayGestureHandler::class.simpleName!!) { /** * Active callbacks, each associated with a tag. Gestures will only be monitored if * [callbacks.size] > 0. */ private val callbacks: MutableMap<String, () -> Unit> = mutableMapOf() private var startY: Float = 0f private var startY: Float = 0f private var startTime: Long = 0L private var startTime: Long = 0L private var monitoringCurrentTouch: Boolean = false private var monitoringCurrentTouch: Boolean = false private var inputMonitor: InputMonitorCompat? = null private var inputReceiver: InputChannelCompat.InputEventReceiver? = null private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize( private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize( com.android.internal.R.dimen.system_gestures_start_threshold com.android.internal.R.dimen.system_gestures_start_threshold ) ) /** Adds a callback that will be triggered when the swipe away gesture is detected. */ override fun onInputEvent(ev: InputEvent) { fun addOnGestureDetectedCallback(tag: String, callback: () -> Unit) { val callbacksWasEmpty = callbacks.isEmpty() callbacks[tag] = callback if (callbacksWasEmpty) { startGestureListening() } } /** Removes the callback. */ fun removeOnGestureDetectedCallback(tag: String) { callbacks.remove(tag) if (callbacks.isEmpty()) { stopGestureListening() } } private fun onInputEvent(ev: InputEvent) { if (ev !is MotionEvent) { if (ev !is MotionEvent) { return return } } Loading Loading @@ -108,7 +80,7 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( ) { ) { monitoringCurrentTouch = false monitoringCurrentTouch = false logger.logGestureDetected(ev.y.toInt()) logger.logGestureDetected(ev.y.toInt()) callbacks.values.forEach { it.invoke() } onGestureDetected() } } } } ACTION_CANCEL, ACTION_UP -> { ACTION_CANCEL, ACTION_UP -> { Loading @@ -120,33 +92,15 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( } } } } /** Start listening for the swipe gesture. */ override fun startGestureListening() { private fun startGestureListening() { super.startGestureListening() stopGestureListening() logger.logInputListeningStarted() logger.logInputListeningStarted() inputMonitor = InputMonitorCompat(TAG, Display.DEFAULT_DISPLAY).also { inputReceiver = it.getInputReceiver( Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent ) } } } /** Stop listening for the swipe gesture. */ override fun stopGestureListening() { private fun stopGestureListening() { super.stopGestureListening() inputMonitor?.let { logger.logInputListeningStopped() logger.logInputListeningStopped() inputMonitor = null it.dispose() } inputReceiver?.let { inputReceiver = null it.dispose() } } } } } private const val SWIPE_TIMEOUT_MS: Long = 500 private const val SWIPE_TIMEOUT_MS: Long = 500 private val TAG = SwipeStatusBarAwayGestureHandler::class.simpleName Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import androidx.annotation.VisibleForTesting import com.android.internal.widget.CachingIconView import com.android.internal.widget.CachingIconView import com.android.systemui.R import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor /** /** Loading @@ -42,6 +43,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( internal val context: Context, internal val context: Context, private val windowManager: WindowManager, private val windowManager: WindowManager, @Main private val mainExecutor: DelayableExecutor, @Main private val mainExecutor: DelayableExecutor, private val tapGestureDetector: TapGestureDetector, @LayoutRes private val chipLayoutRes: Int @LayoutRes private val chipLayoutRes: Int ) { ) { /** The window layout parameters we'll use when attaching the view to a window. */ /** The window layout parameters we'll use when attaching the view to a window. */ Loading Loading @@ -82,6 +84,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // Add view if necessary // Add view if necessary if (oldChipView == null) { if (oldChipView == null) { tapGestureDetector.addOnGestureDetectedCallback(TAG, this::removeChip) windowManager.addView(chipView, windowLayoutParams) windowManager.addView(chipView, windowLayoutParams) } } Loading @@ -96,6 +99,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // TransferTriggered state: Once the user has initiated the transfer, they should be able // TransferTriggered state: Once the user has initiated the transfer, they should be able // to move away from the receiver device but still see the status of the transfer. // to move away from the receiver device but still see the status of the transfer. if (chipView == null) { return } if (chipView == null) { return } tapGestureDetector.removeOnGestureDetectedCallback(TAG) windowManager.removeView(chipView) windowManager.removeView(chipView) chipView = null chipView = null } } Loading Loading @@ -128,5 +132,6 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>( // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and // UpdateMediaTapToTransferReceiverDisplayTest // UpdateMediaTapToTransferReceiverDisplayTest private const val WINDOW_TITLE = "Media Transfer Chip View" private const val WINDOW_TITLE = "Media Transfer Chip View" private val TAG = MediaTttChipControllerCommon::class.simpleName!! @VisibleForTesting @VisibleForTesting const val TIMEOUT_MILLIS = 3000L const val TIMEOUT_MILLIS = 3000L
packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor import javax.inject.Inject import javax.inject.Inject Loading @@ -43,9 +44,10 @@ class MediaTttChipControllerReceiver @Inject constructor( context: Context, context: Context, windowManager: WindowManager, windowManager: WindowManager, mainExecutor: DelayableExecutor, mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, @Main private val mainHandler: Handler, @Main private val mainHandler: Handler, ) : MediaTttChipControllerCommon<ChipStateReceiver>( ) : MediaTttChipControllerCommon<ChipStateReceiver>( context, windowManager, mainExecutor, R.layout.media_ttt_chip_receiver context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip_receiver ) { ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferReceiverDisplay( override fun updateMediaTapToTransferReceiverDisplay( Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor import javax.inject.Inject import javax.inject.Inject Loading @@ -42,9 +43,10 @@ class MediaTttChipControllerSender @Inject constructor( commandQueue: CommandQueue, commandQueue: CommandQueue, context: Context, context: Context, windowManager: WindowManager, windowManager: WindowManager, @Main private val mainExecutor: DelayableExecutor, @Main mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, ) : MediaTttChipControllerCommon<ChipStateSender>( ) : MediaTttChipControllerCommon<ChipStateSender>( context, windowManager, mainExecutor, R.layout.media_ttt_chip context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip ) { ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferSenderDisplay( override fun updateMediaTapToTransferSenderDisplay( Loading
packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt 0 → 100644 +102 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.statusbar.gesture import android.annotation.CallSuper import android.os.Looper import android.view.Choreographer import android.view.Display import android.view.InputEvent import com.android.systemui.shared.system.InputChannelCompat import com.android.systemui.shared.system.InputMonitorCompat /** * An abstract class to help detect gestures that occur anywhere on the display (not specific to a * certain view). * * This class handles starting/stopping the gesture detection system as well as * registering/unregistering callbacks for when gestures occur. Note that the class will only listen * for gestures when there's at least one callback registered. * * Subclasses should implement [onInputEvent] to detect their specific gesture. Once a specific * gesture is detected, they should call [onGestureDetected] (which will notify the callbacks). */ abstract class GenericGestureDetector( private val tag: String ) { /** * Active callbacks, each associated with a tag. Gestures will only be monitored if * [callbacks.size] > 0. */ private val callbacks: MutableMap<String, () -> Unit> = mutableMapOf() private var inputMonitor: InputMonitorCompat? = null private var inputReceiver: InputChannelCompat.InputEventReceiver? = null /** Adds a callback that will be triggered when the tap gesture is detected. */ fun addOnGestureDetectedCallback(tag: String, callback: () -> Unit) { val callbacksWasEmpty = callbacks.isEmpty() callbacks[tag] = callback if (callbacksWasEmpty) { startGestureListening() } } /** Removes the callback. */ fun removeOnGestureDetectedCallback(tag: String) { callbacks.remove(tag) if (callbacks.isEmpty()) { stopGestureListening() } } /** Triggered each time a touch event occurs (and at least one callback is registered). */ abstract fun onInputEvent(ev: InputEvent) /** Should be called by subclasses when their specific gesture is detected. */ internal fun onGestureDetected() { callbacks.values.forEach { it.invoke() } } /** Start listening to touch events. */ @CallSuper internal open fun startGestureListening() { stopGestureListening() inputMonitor = InputMonitorCompat(tag, Display.DEFAULT_DISPLAY).also { inputReceiver = it.getInputReceiver( Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent ) } } /** Stop listening to touch events. */ @CallSuper internal open fun stopGestureListening() { inputMonitor?.let { inputMonitor = null it.dispose() } inputReceiver?.let { inputReceiver = null it.dispose() } } }
packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt +12 −58 Original line number Original line Diff line number Diff line Loading @@ -17,15 +17,13 @@ package com.android.systemui.statusbar.gesture package com.android.systemui.statusbar.gesture import android.content.Context import android.content.Context import android.os.Looper import android.view.Choreographer import android.view.Display import android.view.InputEvent import android.view.InputEvent import android.view.MotionEvent import android.view.MotionEvent import android.view.MotionEvent.* import android.view.MotionEvent.ACTION_CANCEL import android.view.MotionEvent.ACTION_DOWN import android.view.MotionEvent.ACTION_MOVE import android.view.MotionEvent.ACTION_UP import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shared.system.InputChannelCompat import com.android.systemui.shared.system.InputMonitorCompat import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.statusbar.window.StatusBarWindowController import javax.inject.Inject import javax.inject.Inject Loading @@ -38,43 +36,17 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( context: Context, context: Context, private val statusBarWindowController: StatusBarWindowController, private val statusBarWindowController: StatusBarWindowController, private val logger: SwipeStatusBarAwayGestureLogger private val logger: SwipeStatusBarAwayGestureLogger ) { ) : GenericGestureDetector(SwipeStatusBarAwayGestureHandler::class.simpleName!!) { /** * Active callbacks, each associated with a tag. Gestures will only be monitored if * [callbacks.size] > 0. */ private val callbacks: MutableMap<String, () -> Unit> = mutableMapOf() private var startY: Float = 0f private var startY: Float = 0f private var startTime: Long = 0L private var startTime: Long = 0L private var monitoringCurrentTouch: Boolean = false private var monitoringCurrentTouch: Boolean = false private var inputMonitor: InputMonitorCompat? = null private var inputReceiver: InputChannelCompat.InputEventReceiver? = null private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize( private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize( com.android.internal.R.dimen.system_gestures_start_threshold com.android.internal.R.dimen.system_gestures_start_threshold ) ) /** Adds a callback that will be triggered when the swipe away gesture is detected. */ override fun onInputEvent(ev: InputEvent) { fun addOnGestureDetectedCallback(tag: String, callback: () -> Unit) { val callbacksWasEmpty = callbacks.isEmpty() callbacks[tag] = callback if (callbacksWasEmpty) { startGestureListening() } } /** Removes the callback. */ fun removeOnGestureDetectedCallback(tag: String) { callbacks.remove(tag) if (callbacks.isEmpty()) { stopGestureListening() } } private fun onInputEvent(ev: InputEvent) { if (ev !is MotionEvent) { if (ev !is MotionEvent) { return return } } Loading Loading @@ -108,7 +80,7 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( ) { ) { monitoringCurrentTouch = false monitoringCurrentTouch = false logger.logGestureDetected(ev.y.toInt()) logger.logGestureDetected(ev.y.toInt()) callbacks.values.forEach { it.invoke() } onGestureDetected() } } } } ACTION_CANCEL, ACTION_UP -> { ACTION_CANCEL, ACTION_UP -> { Loading @@ -120,33 +92,15 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( } } } } /** Start listening for the swipe gesture. */ override fun startGestureListening() { private fun startGestureListening() { super.startGestureListening() stopGestureListening() logger.logInputListeningStarted() logger.logInputListeningStarted() inputMonitor = InputMonitorCompat(TAG, Display.DEFAULT_DISPLAY).also { inputReceiver = it.getInputReceiver( Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent ) } } } /** Stop listening for the swipe gesture. */ override fun stopGestureListening() { private fun stopGestureListening() { super.stopGestureListening() inputMonitor?.let { logger.logInputListeningStopped() logger.logInputListeningStopped() inputMonitor = null it.dispose() } inputReceiver?.let { inputReceiver = null it.dispose() } } } } } private const val SWIPE_TIMEOUT_MS: Long = 500 private const val SWIPE_TIMEOUT_MS: Long = 500 private val TAG = SwipeStatusBarAwayGestureHandler::class.simpleName