• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.res.Configuration
20 import android.content.res.Resources
21 import android.util.MathUtils.constrain
22 import com.android.systemui.R
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.dagger.qualifiers.Main
25 import com.android.systemui.dump.DumpManager
26 import com.android.systemui.flags.FeatureFlags
27 import com.android.systemui.flags.Flags
28 import com.android.systemui.shade.PanelState
29 import com.android.systemui.shade.STATE_OPENING
30 import com.android.systemui.shade.ShadeExpansionChangeEvent
31 import com.android.systemui.statusbar.StatusBarState
32 import com.android.systemui.statusbar.SysuiStatusBarStateController
33 import com.android.systemui.statusbar.phone.ScrimController
34 import com.android.systemui.statusbar.policy.ConfigurationController
35 import com.android.systemui.statusbar.policy.HeadsUpManager
36 import com.android.systemui.util.LargeScreenUtils
37 import java.io.PrintWriter
38 import javax.inject.Inject
39 
40 /** Controls the scrim properties during the shade expansion transition on non-lockscreen. */
41 @SysUISingleton
42 class ScrimShadeTransitionController
43 @Inject
44 constructor(
45     configurationController: ConfigurationController,
46     dumpManager: DumpManager,
47     private val scrimController: ScrimController,
48     @Main private val resources: Resources,
49     private val statusBarStateController: SysuiStatusBarStateController,
50     private val headsUpManager: HeadsUpManager,
51     private val featureFlags: FeatureFlags,
52 ) {
53 
54     private var inSplitShade = false
55     private var splitShadeScrimTransitionDistance = 0
56     private var lastExpansionFraction: Float? = null
57     private var lastExpansionEvent: ShadeExpansionChangeEvent? = null
58     private var currentPanelState: Int? = null
59 
60     init {
61         updateResources()
62         configurationController.addCallback(
63             object : ConfigurationController.ConfigurationListener {
onConfigChangednull64                 override fun onConfigChanged(newConfig: Configuration?) {
65                     updateResources()
66                 }
67             })
68         dumpManager.registerDumpable(
69             ScrimShadeTransitionController::class.java.simpleName, this::dump)
70     }
71 
updateResourcesnull72     private fun updateResources() {
73         inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(resources)
74         splitShadeScrimTransitionDistance =
75             resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance)
76     }
77 
onPanelStateChangednull78     fun onPanelStateChanged(@PanelState state: Int) {
79         currentPanelState = state
80         onStateChanged()
81     }
82 
onPanelExpansionChangednull83     fun onPanelExpansionChanged(shadeExpansionChangeEvent: ShadeExpansionChangeEvent) {
84         lastExpansionEvent = shadeExpansionChangeEvent
85         onStateChanged()
86     }
87 
onStateChangednull88     private fun onStateChanged() {
89         val expansionEvent = lastExpansionEvent ?: return
90         val panelState = currentPanelState
91         val expansionFraction = calculateScrimExpansionFraction(expansionEvent, panelState)
92         scrimController.setRawPanelExpansionFraction(expansionFraction)
93         lastExpansionFraction = expansionFraction
94     }
95 
calculateScrimExpansionFractionnull96     private fun calculateScrimExpansionFraction(
97         expansionEvent: ShadeExpansionChangeEvent,
98         @PanelState panelState: Int?
99     ): Float {
100         return if (canUseCustomFraction(panelState)) {
101             constrain(expansionEvent.dragDownPxAmount / splitShadeScrimTransitionDistance, 0f, 1f)
102         } else {
103             expansionEvent.fraction
104         }
105     }
106 
canUseCustomFractionnull107     private fun canUseCustomFraction(panelState: Int?) =
108         inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING &&
109                 // in case of HUN we can't always use predefined distances to manage scrim
110                 // transition because dragDownPxAmount can start from value bigger than
111                 // splitShadeScrimTransitionDistance
112                 !headsUpManager.isTrackingHeadsUp &&
113                 !featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
114 
115     private fun isScreenUnlocked() =
116         statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
117 
118     private fun dump(printWriter: PrintWriter, args: Array<String>) {
119         printWriter.println(
120             """
121                 ScrimShadeTransitionController:
122                   Resources:
123                     inSplitShade: $inSplitShade
124                     isScreenUnlocked: ${isScreenUnlocked()}
125                     splitShadeScrimTransitionDistance: $splitShadeScrimTransitionDistance
126                   State:
127                     currentPanelState: $currentPanelState
128                     lastExpansionFraction: $lastExpansionFraction
129                     lastExpansionEvent: $lastExpansionEvent
130             """.trimIndent())
131     }
132 }
133