1 /*
2  * Copyright (C) 2020 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.init
18 
19 import android.service.notification.StatusBarNotification
20 import com.android.systemui.dagger.SysUISingleton
21 import com.android.systemui.flags.FeatureFlags
22 import com.android.systemui.people.widget.PeopleSpaceWidgetManager
23 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
24 import com.android.systemui.statusbar.NotificationListener
25 import com.android.systemui.statusbar.NotificationMediaManager
26 import com.android.systemui.statusbar.NotificationPresenter
27 import com.android.systemui.statusbar.notification.AnimatedImageNotificationManager
28 import com.android.systemui.statusbar.notification.NotificationActivityStarter
29 import com.android.systemui.statusbar.notification.NotificationClicker
30 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
31 import com.android.systemui.statusbar.notification.collection.NotifPipeline
32 import com.android.systemui.statusbar.notification.collection.NotificationEntry
33 import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
34 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
35 import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
36 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
37 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
38 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
39 import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
40 import com.android.systemui.statusbar.notification.logging.NotificationLogger
41 import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
42 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
43 import com.android.wm.shell.bubbles.Bubbles
44 import dagger.Lazy
45 import java.util.Optional
46 import javax.inject.Inject
47 
48 /**
49  * Master controller for all notifications-related work
50  *
51  * At the moment exposes a number of event-handler-esque methods; these are for historical reasons.
52  * Once we migrate away from the need for such things, this class becomes primarily a place to do
53  * any initialization work that notifications require.
54  */
55 @SysUISingleton
56 class NotificationsControllerImpl @Inject constructor(
57     private val notificationListener: NotificationListener,
58     private val commonNotifCollection: Lazy<CommonNotifCollection>,
59     private val notifPipeline: Lazy<NotifPipeline>,
60     private val notifLiveDataStore: NotifLiveDataStore,
61     private val targetSdkResolver: TargetSdkResolver,
62     private val notifPipelineInitializer: Lazy<NotifPipelineInitializer>,
63     private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
64     private val notificationLogger: NotificationLogger,
65     private val notificationRowBinder: NotificationRowBinderImpl,
66     private val notificationsMediaManager: NotificationMediaManager,
67     private val headsUpViewBinder: HeadsUpViewBinder,
68     private val clickerBuilder: NotificationClicker.Builder,
69     private val animatedImageNotificationManager: AnimatedImageNotificationManager,
70     private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager,
71     private val bubblesOptional: Optional<Bubbles>,
72     private val featureFlags: FeatureFlags
73 ) : NotificationsController {
74 
75     override fun initialize(
76         presenter: NotificationPresenter,
77         listContainer: NotificationListContainer,
78         stackController: NotifStackController,
79         notificationActivityStarter: NotificationActivityStarter,
80     ) {
81         notificationListener.registerAsSystemService()
82 
83         notifPipeline.get().addCollectionListener(object : NotifCollectionListener {
84             override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
85                 listContainer.cleanUpViewStateForEntry(entry)
86             }
87         })
88 
89         notificationRowBinder.setNotificationClicker(
90             clickerBuilder.build(bubblesOptional, notificationActivityStarter))
91         notificationRowBinder.setUpWithPresenter(presenter, listContainer)
92         headsUpViewBinder.setPresenter(presenter)
93         notifBindPipelineInitializer.initialize()
94         animatedImageNotificationManager.bind()
95 
96         notifPipelineInitializer.get().initialize(
97                 notificationListener,
98                 notificationRowBinder,
99                 listContainer,
100                 stackController)
101 
102         targetSdkResolver.initialize(notifPipeline.get())
103         notificationsMediaManager.setUpWithPresenter(presenter)
104         notificationLogger.setUpWithContainer(listContainer)
105         peopleSpaceWidgetManager.attach(notificationListener)
106     }
107 
108     // TODO: Convert all functions below this line into listeners instead of public methods
109 
110     override fun resetUserExpandedStates() {
111         // TODO: this is a view thing that should be done through the views, but that means doing it
112         //  both when this event is fired and any time a row is attached.
113         for (entry in commonNotifCollection.get().allNotifs) {
114             entry.resetUserExpansion()
115         }
116     }
117 
118     override fun setNotificationSnoozed(sbn: StatusBarNotification, snoozeOption: SnoozeOption) {
119         if (snoozeOption.snoozeCriterion != null) {
120             notificationListener.snoozeNotification(sbn.key, snoozeOption.snoozeCriterion.id)
121         } else {
122             notificationListener.snoozeNotification(
123                     sbn.key,
124                     snoozeOption.minutesToSnoozeFor * 60 * 1000.toLong())
125         }
126     }
127 
128     override fun getActiveNotificationsCount(): Int =
129         notifLiveDataStore.activeNotifCount.value
130 }
131