1 /*
2  * 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.statusbar.notification.dagger
18 
19 import com.android.systemui.CoreStartable
20 import com.android.systemui.NoOpCoreStartable
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.dagger.qualifiers.UiBackground
23 import com.android.systemui.plugins.statusbar.StatusBarStateController
24 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
25 import com.android.systemui.statusbar.NotificationListener
26 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
27 import com.android.systemui.statusbar.notification.collection.NotifPipeline
28 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider
29 import com.android.systemui.statusbar.notification.logging.NotificationLogger
30 import com.android.systemui.statusbar.notification.logging.NotificationLogger.ExpansionStateLogger
31 import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger
32 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
33 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationRowStatsLogger
34 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger
35 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLoggerImpl
36 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLoggerViewModel
37 import com.android.systemui.util.kotlin.JavaAdapter
38 import com.android.systemui.util.kotlin.getOrNull
39 import dagger.Binds
40 import dagger.Module
41 import dagger.Provides
42 import dagger.multibindings.ClassKey
43 import dagger.multibindings.IntoMap
44 import java.util.Optional
45 import java.util.concurrent.Executor
46 import javax.inject.Provider
47 
48 @Module
49 interface NotificationStatsLoggerModule {
50 
51     /** Binds an implementation to the [NotificationStatsLogger]. */
bindsStatsLoggerImplnull52     @Binds fun bindsStatsLoggerImpl(impl: NotificationStatsLoggerImpl): NotificationStatsLogger
53 
54     companion object {
55 
56         /** Provides a [NotificationStatsLogger] if the refactor flag is on. */
57         @Provides
58         fun provideStatsLogger(
59             provider: Provider<NotificationStatsLogger>
60         ): Optional<NotificationStatsLogger> {
61             return if (NotificationsLiveDataStoreRefactor.isEnabled) {
62                 Optional.of(provider.get())
63             } else {
64                 Optional.empty()
65             }
66         }
67 
68         /** Provides a [NotificationLoggerViewModel] if the refactor flag is on. */
69         @Provides
70         fun provideViewModel(
71             provider: Provider<NotificationLoggerViewModel>
72         ): Optional<NotificationLoggerViewModel> {
73             return if (NotificationsLiveDataStoreRefactor.isEnabled) {
74                 Optional.of(provider.get())
75             } else {
76                 Optional.empty()
77             }
78         }
79 
80         /** Provides the legacy [NotificationLogger] if the refactor flag is off. */
81         @Provides
82         @SysUISingleton
83         fun provideLegacyLoggerOptional(
84             notificationListener: NotificationListener?,
85             @UiBackground uiBgExecutor: Executor?,
86             notifLiveDataStore: NotifLiveDataStore?,
87             visibilityProvider: NotificationVisibilityProvider?,
88             notifPipeline: NotifPipeline?,
89             statusBarStateController: StatusBarStateController?,
90             windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor?,
91             javaAdapter: JavaAdapter?,
92             expansionStateLogger: ExpansionStateLogger?,
93             notificationPanelLogger: NotificationPanelLogger?
94         ): Optional<NotificationLogger> {
95             return if (NotificationsLiveDataStoreRefactor.isEnabled) {
96                 Optional.empty()
97             } else {
98                 Optional.of(
99                     NotificationLogger(
100                         notificationListener,
101                         uiBgExecutor,
102                         notifLiveDataStore,
103                         visibilityProvider,
104                         notifPipeline,
105                         statusBarStateController,
106                         windowRootViewVisibilityInteractor,
107                         javaAdapter,
108                         expansionStateLogger,
109                         notificationPanelLogger
110                     )
111                 )
112             }
113         }
114 
115         /**
116          * Provides a the legacy [NotificationLogger] or the new [NotificationStatsLogger] to the
117          * notification row.
118          *
119          * TODO(b/308623704) remove the [NotificationRowStatsLogger] interface, and provide a
120          *   [NotificationStatsLogger] to the row directly.
121          */
122         @Provides
123         fun provideRowStatsLogger(
124             newProvider: Provider<NotificationStatsLogger>,
125             legacyLoggerOptional: Optional<NotificationLogger>,
126         ): NotificationRowStatsLogger {
127             return legacyLoggerOptional.getOrNull() ?: newProvider.get()
128         }
129 
130         /**
131          * Binds the legacy [NotificationLogger] as a [CoreStartable] if the feature flag is off, or
132          * binds a no-op [CoreStartable] otherwise.
133          *
134          * The old [NotificationLogger] is a [CoreStartable], because it's managing its own data
135          * updates, but the new [NotificationStatsLogger] is not. Currently Dagger doesn't support
136          * optionally binding entries with @[IntoMap], therefore we provide a no-op [CoreStartable]
137          * here if the feature flag is on, but this can be removed once the flag is released.
138          */
139         @Provides
140         @IntoMap
141         @ClassKey(NotificationLogger::class)
142         fun provideCoreStartable(
143             legacyLoggerOptional: Optional<NotificationLogger>
144         ): CoreStartable {
145             return legacyLoggerOptional.getOrNull() ?: NoOpCoreStartable()
146         }
147     }
148 }
149