1 /*
2  * Copyright (C) 2021 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.statusbar.notification.collection.coordinator
18 
19 import com.android.internal.widget.MessagingGroup
20 import com.android.internal.widget.MessagingMessage
21 import com.android.keyguard.KeyguardUpdateMonitor
22 import com.android.systemui.flags.FeatureFlags
23 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
24 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl
25 import com.android.systemui.statusbar.notification.collection.NotifPipeline
26 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
27 import com.android.systemui.statusbar.notification.row.NotificationGutsManager
28 import com.android.systemui.statusbar.policy.ConfigurationController
29 import javax.inject.Inject
30 
31 /**
32  * A coordinator which ensures that notifications within the new pipeline are correctly inflated
33  * for the current uiMode and screen properties; additionally deferring those changes when a user
34  * change is in progress until that process has completed.
35  */
36 @CoordinatorScope
37 class ViewConfigCoordinator @Inject internal constructor(
38     configurationController: ConfigurationController,
39     lockscreenUserManager: NotificationLockscreenUserManagerImpl,
40     featureFlags: FeatureFlags,
41     private val mGutsManager: NotificationGutsManager,
42     private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor
43 ) : Coordinator, UserChangedListener, ConfigurationController.ConfigurationListener {
44 
45     private var mReinflateNotificationsOnUserSwitched = false
46     private var mDispatchUiModeChangeOnUserSwitched = false
47     private var mPipeline: NotifPipeline? = null
48 
49     init {
50         if (featureFlags.isNewNotifPipelineRenderingEnabled) {
51             lockscreenUserManager.addUserChangedListener(this)
52             configurationController.addCallback(this)
53         }
54     }
55 
56     override fun attach(pipeline: NotifPipeline) {
57         mPipeline = pipeline
58     }
59 
60     override fun onDensityOrFontScaleChanged() {
61         MessagingMessage.dropCache()
62         MessagingGroup.dropCache()
63         if (!mKeyguardUpdateMonitor.isSwitchingUser) {
64             updateNotificationsOnDensityOrFontScaleChanged()
65         } else {
66             mReinflateNotificationsOnUserSwitched = true
67         }
68     }
69 
70     override fun onUiModeChanged() {
71         if (!mKeyguardUpdateMonitor.isSwitchingUser) {
72             updateNotificationsOnUiModeChanged()
73         } else {
74             mDispatchUiModeChangeOnUserSwitched = true
75         }
76     }
77 
78     override fun onThemeChanged() {
79         onDensityOrFontScaleChanged()
80     }
81 
82     override fun onUserChanged(userId: Int) {
83         if (mReinflateNotificationsOnUserSwitched) {
84             updateNotificationsOnDensityOrFontScaleChanged()
85             mReinflateNotificationsOnUserSwitched = false
86         }
87         if (mDispatchUiModeChangeOnUserSwitched) {
88             updateNotificationsOnUiModeChanged()
89             mDispatchUiModeChangeOnUserSwitched = false
90         }
91     }
92 
93     private fun updateNotificationsOnUiModeChanged() {
94         mPipeline?.allNotifs?.forEach { entry ->
95             val row = entry.row
96             row?.onUiModeChanged()
97         }
98     }
99 
100     private fun updateNotificationsOnDensityOrFontScaleChanged() {
101         mPipeline?.allNotifs?.forEach { entry ->
102             entry.onDensityOrFontScaleChanged()
103             val exposedGuts = entry.areGutsExposed()
104             if (exposedGuts) {
105                 mGutsManager.onDensityOrFontScaleChanged(entry)
106             }
107         }
108     }
109 }