• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.back.domain.interactor
18 
19 import android.window.BackEvent
20 import android.window.OnBackAnimationCallback
21 import android.window.OnBackInvokedCallback
22 import android.window.OnBackInvokedDispatcher
23 import android.window.WindowOnBackInvokedDispatcher
24 import com.android.app.tracing.coroutines.launchTraced as launch
25 import com.android.systemui.CoreStartable
26 import com.android.systemui.Flags.predictiveBackAnimateShade
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.dagger.qualifiers.Application
29 import com.android.systemui.plugins.statusbar.StatusBarStateController
30 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
31 import com.android.systemui.shade.QuickSettingsController
32 import com.android.systemui.shade.ShadeController
33 import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor
34 import com.android.systemui.statusbar.NotificationShadeWindowController
35 import com.android.systemui.statusbar.StatusBarState
36 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
37 import javax.inject.Inject
38 import kotlinx.coroutines.CoroutineScope
39 
40 /** Handles requests to go back either from a button or gesture. */
41 @SysUISingleton
42 class BackActionInteractor
43 @Inject
44 constructor(
45     @Application private val scope: CoroutineScope,
46     private val statusBarStateController: StatusBarStateController,
47     private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
48     private val shadeController: ShadeController,
49     private val notificationShadeWindowController: NotificationShadeWindowController,
50     private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor,
51     private val shadeBackActionInteractor: ShadeBackActionInteractor,
52     private val qsController: QuickSettingsController,
53 ) : CoreStartable {
54 
55     private var isCallbackRegistered = false
56 
57     private val callback =
58         if (predictiveBackAnimateShade()) {
59             /**
60              * New callback that handles back gesture invoked, cancel, progress and provides
61              * feedback via Shade animation.
62              */
63             object : OnBackAnimationCallback {
64                 override fun onBackInvoked() {
65                     onBackRequested()
66                 }
67 
68                 override fun onBackProgressed(backEvent: BackEvent) {
69                     if (shouldBackBeHandled() && shadeBackActionInteractor.canBeCollapsed()) {
70                         shadeBackActionInteractor.onBackProgressed(backEvent.progress)
71                     }
72                 }
73             }
74         } else {
75             OnBackInvokedCallback { onBackRequested() }
76         }
77 
78     private val onBackInvokedDispatcher: WindowOnBackInvokedDispatcher?
79         get() =
80             notificationShadeWindowController.windowRootView?.viewRootImpl?.onBackInvokedDispatcher
81 
82     override fun start() {
83         scope.launch {
84             windowRootViewVisibilityInteractor.isLockscreenOrShadeVisibleAndInteractive.collect {
85                 visible ->
86                 if (visible) {
87                     registerBackCallback()
88                 } else {
89                     unregisterBackCallback()
90                 }
91             }
92         }
93     }
94 
95     fun shouldBackBeHandled(): Boolean {
96         return statusBarStateController.state != StatusBarState.KEYGUARD &&
97             statusBarStateController.state != StatusBarState.SHADE_LOCKED &&
98             !statusBarKeyguardViewManager.isBouncerShowingOverDream
99     }
100 
101     fun onBackRequested(): Boolean {
102         if (statusBarKeyguardViewManager.canHandleBackPressed()) {
103             statusBarKeyguardViewManager.onBackPressed()
104             return true
105         }
106         if (qsController.isCustomizing) {
107             qsController.closeQsCustomizer()
108             return true
109         }
110         if (qsController.expanded) {
111             shadeBackActionInteractor.animateCollapseQs(false)
112             return true
113         }
114         if (shouldBackBeHandled()) {
115             if (shadeBackActionInteractor.canBeCollapsed()) {
116                 // this is the Shade dismiss animation, so make sure QQS closes when it ends.
117                 shadeBackActionInteractor.onBackPressed()
118                 shadeController.animateCollapseShade()
119             }
120             return true
121         }
122         return false
123     }
124 
125     fun isBackCallbackRegistered(): Boolean {
126         return isCallbackRegistered
127     }
128 
129     private fun registerBackCallback() {
130         if (isCallbackRegistered) {
131             return
132         }
133         onBackInvokedDispatcher?.let {
134             it.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback)
135             isCallbackRegistered = true
136         }
137     }
138 
139     private fun unregisterBackCallback() {
140         if (!isCallbackRegistered) {
141             return
142         }
143         onBackInvokedDispatcher?.let {
144             it.unregisterOnBackInvokedCallback(callback)
145             isCallbackRegistered = false
146         }
147     }
148 }
149