1 /*
<lambda>null2  * 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.collection.coordinator
18 
19 import com.android.systemui.dagger.qualifiers.Application
20 import com.android.systemui.keyguard.data.repository.KeyguardRepository
21 import com.android.systemui.plugins.statusbar.StatusBarStateController
22 import com.android.systemui.statusbar.StatusBarState
23 import com.android.systemui.statusbar.SysuiStatusBarStateController
24 import com.android.systemui.statusbar.notification.collection.NotifPipeline
25 import com.android.systemui.statusbar.notification.collection.NotificationEntry
26 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
27 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
28 import javax.inject.Inject
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.launch
31 
32 /**
33  * Filter out notifications on the lockscreen if the lockscreen hosted dream is active. If the user
34  * stops dreaming, pulls the shade down or unlocks the device, then the notifications are unhidden.
35  */
36 @CoordinatorScope
37 class DreamCoordinator
38 @Inject
39 constructor(
40     private val statusBarStateController: SysuiStatusBarStateController,
41     @Application private val scope: CoroutineScope,
42     private val keyguardRepository: KeyguardRepository,
43 ) : Coordinator {
44     private var isOnKeyguard = false
45     private var isLockscreenHostedDream = false
46 
47     override fun attach(pipeline: NotifPipeline) {
48         pipeline.addPreGroupFilter(filter)
49         statusBarStateController.addCallback(statusBarStateListener)
50         scope.launch { attachFilterOnDreamingStateChange() }
51         recordStatusBarState(statusBarStateController.state)
52     }
53 
54     private val filter =
55         object : NotifFilter("LockscreenHostedDreamFilter") {
56             var isFiltering = false
57             override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean {
58                 return isFiltering
59             }
60             inline fun update(msg: () -> String) {
61                 val wasFiltering = isFiltering
62                 isFiltering = isLockscreenHostedDream && isOnKeyguard
63                 if (wasFiltering != isFiltering) {
64                     invalidateList(msg())
65                 }
66             }
67         }
68 
69     private val statusBarStateListener =
70         object : StatusBarStateController.StateListener {
71             override fun onStateChanged(newState: Int) {
72                 recordStatusBarState(newState)
73             }
74         }
75 
76     private suspend fun attachFilterOnDreamingStateChange() {
77         keyguardRepository.isActiveDreamLockscreenHosted.collect { isDreaming ->
78             recordDreamingState(isDreaming)
79         }
80     }
81 
82     private fun recordStatusBarState(newState: Int) {
83         isOnKeyguard = newState == StatusBarState.KEYGUARD
84         filter.update { "recordStatusBarState: " + StatusBarState.toString(newState) }
85     }
86 
87     private fun recordDreamingState(isDreaming: Boolean) {
88         isLockscreenHostedDream = isDreaming
89         filter.update { "recordLockscreenHostedDreamState: $isDreaming" }
90     }
91 }
92