• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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 android.util.Log
20 import com.android.app.tracing.traceSection
21 import com.android.internal.widget.MessagingGroup
22 import com.android.internal.widget.MessagingMessage
23 import com.android.keyguard.KeyguardUpdateMonitor
24 import com.android.keyguard.KeyguardUpdateMonitorCallback
25 import com.android.systemui.shade.ShadeDisplayAware
26 import com.android.systemui.statusbar.NotificationLockscreenUserManager
27 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
28 import com.android.systemui.statusbar.notification.ColorUpdateLogger
29 import com.android.systemui.statusbar.notification.collection.NotifPipeline
30 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
31 import com.android.systemui.statusbar.notification.row.NotificationGutsManager
32 import com.android.systemui.statusbar.policy.ConfigurationController
33 import com.android.systemui.util.Compile
34 import javax.inject.Inject
35 
36 /**
37  * A coordinator which ensures that notifications within the new pipeline are correctly inflated for
38  * the current uiMode and screen properties; additionally deferring those changes when a user change
39  * is in progress until that process has completed.
40  */
41 @CoordinatorScope
42 class ViewConfigCoordinator
43 @Inject
44 internal constructor(
45     @ShadeDisplayAware private val mConfigurationController: ConfigurationController,
46     private val mLockscreenUserManager: NotificationLockscreenUserManager,
47     private val mGutsManager: NotificationGutsManager,
48     private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor,
49     private val colorUpdateLogger: ColorUpdateLogger,
50 ) : Coordinator, ConfigurationController.ConfigurationListener {
51 
52     private var mIsSwitchingUser = false
53     private var mReinflateNotificationsOnUserSwitched = false
54     private var mDispatchUiModeChangeOnUserSwitched = false
55     private var mPipeline: NotifPipeline? = null
56 
57     private val mKeyguardUpdateCallback =
58         object : KeyguardUpdateMonitorCallback() {
59             override fun onUserSwitching(userId: Int) {
60                 colorUpdateLogger.logTriggerEvent("VCC.mKeyguardUpdateCallback.onUserSwitching()")
61                 log { "ViewConfigCoordinator.onUserSwitching(userId=$userId)" }
62                 mIsSwitchingUser = true
63             }
64 
65             override fun onUserSwitchComplete(userId: Int) {
66                 colorUpdateLogger.logTriggerEvent(
67                     "VCC.mKeyguardUpdateCallback.onUserSwitchComplete()"
68                 )
69                 log { "ViewConfigCoordinator.onUserSwitchComplete(userId=$userId)" }
70                 mIsSwitchingUser = false
71                 applyChangesOnUserSwitched()
72             }
73         }
74 
75     private val mUserChangedListener =
76         object : UserChangedListener {
77             override fun onUserChanged(userId: Int) {
78                 colorUpdateLogger.logTriggerEvent("VCC.mUserChangedListener.onUserChanged()")
79                 log { "ViewConfigCoordinator.onUserChanged(userId=$userId)" }
80                 applyChangesOnUserSwitched()
81             }
82         }
83 
84     override fun attach(pipeline: NotifPipeline) {
85         mPipeline = pipeline
86         mLockscreenUserManager.addUserChangedListener(mUserChangedListener)
87         mConfigurationController.addCallback(this)
88         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback)
89     }
90 
91     override fun onDensityOrFontScaleChanged() {
92         colorUpdateLogger.logTriggerEvent("VCC.onDensityOrFontScaleChanged()")
93         log {
94             val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser
95             "ViewConfigCoordinator.onDensityOrFontScaleChanged()" +
96                 " isSwitchingUser=$mIsSwitchingUser" +
97                 " keyguardUpdateMonitor.isSwitchingUser=$keyguardIsSwitchingUser"
98         }
99         MessagingMessage.dropCache()
100         MessagingGroup.dropCache()
101         if (!mIsSwitchingUser) {
102             updateNotificationsOnDensityOrFontScaleChanged()
103         } else {
104             mReinflateNotificationsOnUserSwitched = true
105         }
106     }
107 
108     override fun onUiModeChanged() {
109         colorUpdateLogger.logTriggerEvent("VCC.onUiModeChanged()")
110         log {
111             val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser
112             "ViewConfigCoordinator.onUiModeChanged()" +
113                 " isSwitchingUser=$mIsSwitchingUser" +
114                 " keyguardUpdateMonitor.isSwitchingUser=$keyguardIsSwitchingUser"
115         }
116         if (!mIsSwitchingUser) {
117             updateNotificationsOnUiModeChanged()
118         } else {
119             mDispatchUiModeChangeOnUserSwitched = true
120         }
121     }
122 
123     override fun onThemeChanged() {
124         colorUpdateLogger.logTriggerEvent("VCC.onThemeChanged()")
125         onDensityOrFontScaleChanged()
126     }
127 
128     private fun applyChangesOnUserSwitched() {
129         colorUpdateLogger.logEvent("VCC.applyChangesOnUserSwitched()")
130         if (mReinflateNotificationsOnUserSwitched) {
131             updateNotificationsOnDensityOrFontScaleChanged()
132             mReinflateNotificationsOnUserSwitched = false
133         }
134         if (mDispatchUiModeChangeOnUserSwitched) {
135             updateNotificationsOnUiModeChanged()
136             mDispatchUiModeChangeOnUserSwitched = false
137         }
138     }
139 
140     private fun updateNotificationsOnUiModeChanged() {
141         colorUpdateLogger.logEvent(
142             "VCC.updateNotificationsOnUiModeChanged()",
143             "mode=" + mConfigurationController.nightModeName,
144         )
145         log { "ViewConfigCoordinator.updateNotificationsOnUiModeChanged()" }
146         traceSection("updateNotifOnUiModeChanged") {
147             mPipeline?.allNotifs?.forEach { entry ->
148                 entry.row?.onUiModeChanged()
149                 mGutsManager.closeAndUndoGuts()
150             }
151         }
152     }
153 
154     private fun updateNotificationsOnDensityOrFontScaleChanged() {
155         colorUpdateLogger.logEvent("VCC.updateNotificationsOnDensityOrFontScaleChanged()")
156         mPipeline?.allNotifs?.forEach { entry ->
157             entry.onDensityOrFontScaleChanged()
158             mGutsManager.closeAndUndoGuts()
159         }
160     }
161 
162     private inline fun log(message: () -> String) {
163         if (DEBUG) Log.d(TAG, message())
164     }
165 
166     companion object {
167         private const val TAG = "ViewConfigCoordinator"
168         private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG)
169     }
170 }
171