1 /*
2  * 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.transition
18 
19 import android.content.Context
20 import android.content.res.Configuration
21 import com.android.systemui.R
22 import com.android.systemui.dagger.SysUISingleton
23 import com.android.systemui.dump.DumpManager
24 import com.android.systemui.plugins.qs.QS
25 import com.android.systemui.shade.PanelState
26 import com.android.systemui.shade.ShadeExpansionChangeEvent
27 import com.android.systemui.shade.ShadeExpansionStateManager
28 import com.android.systemui.shade.ShadeViewController
29 import com.android.systemui.shade.panelStateToString
30 import com.android.systemui.statusbar.StatusBarState
31 import com.android.systemui.statusbar.SysuiStatusBarStateController
32 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
33 import com.android.systemui.statusbar.policy.ConfigurationController
34 import java.io.PrintWriter
35 import javax.inject.Inject
36 
37 /** Controls the shade expansion transition on non-lockscreen. */
38 @SysUISingleton
39 class ShadeTransitionController
40 @Inject
41 constructor(
42     configurationController: ConfigurationController,
43     shadeExpansionStateManager: ShadeExpansionStateManager,
44     dumpManager: DumpManager,
45     private val context: Context,
46     private val scrimShadeTransitionController: ScrimShadeTransitionController,
47     private val statusBarStateController: SysuiStatusBarStateController,
48 ) {
49 
50     lateinit var shadeViewController: ShadeViewController
51     lateinit var notificationStackScrollLayoutController: NotificationStackScrollLayoutController
52     lateinit var qs: QS
53 
54     private var inSplitShade = false
55     private var currentPanelState: Int? = null
56     private var lastShadeExpansionChangeEvent: ShadeExpansionChangeEvent? = null
57 
58     init {
59         updateResources()
60         configurationController.addCallback(
61             object : ConfigurationController.ConfigurationListener {
62                 override fun onConfigChanged(newConfig: Configuration?) {
63                     updateResources()
64                 }
65             })
66         val currentState =
67             shadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged)
68         onPanelExpansionChanged(currentState)
69         shadeExpansionStateManager.addStateListener(this::onPanelStateChanged)
70         dumpManager.registerCriticalDumpable("ShadeTransitionController") { printWriter, _ ->
71             dump(printWriter)
72         }
73     }
74 
75     private fun updateResources() {
76         inSplitShade = context.resources.getBoolean(R.bool.config_use_split_notification_shade)
77     }
78 
79     private fun onPanelStateChanged(@PanelState state: Int) {
80         currentPanelState = state
81         scrimShadeTransitionController.onPanelStateChanged(state)
82     }
83 
84     private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
85         lastShadeExpansionChangeEvent = event
86         scrimShadeTransitionController.onPanelExpansionChanged(event)
87     }
88 
89     private fun dump(pw: PrintWriter) {
90         pw.println(
91             """
92             ShadeTransitionController:
93                 inSplitShade: $inSplitShade
94                 isScreenUnlocked: ${isScreenUnlocked()}
95                 currentPanelState: ${currentPanelState?.panelStateToString()}
96                 lastPanelExpansionChangeEvent: $lastShadeExpansionChangeEvent
97                 qs.isInitialized: ${this::qs.isInitialized}
98                 npvc.isInitialized: ${this::shadeViewController.isInitialized}
99                 nssl.isInitialized: ${this::notificationStackScrollLayoutController.isInitialized}
100             """.trimIndent())
101     }
102 
103     private fun isScreenUnlocked() =
104         statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
105 }
106