• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.data.repository
18 
19 import com.android.systemui.dagger.SysUISingleton
20 import com.android.systemui.dagger.qualifiers.Application
21 import com.android.systemui.scene.shared.flag.SceneContainerFlag
22 import com.android.systemui.statusbar.NotificationRemoteInputManager
23 import com.android.systemui.statusbar.RemoteInputController
24 import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
25 import dagger.Binds
26 import dagger.Module
27 import javax.inject.Inject
28 import kotlinx.coroutines.CoroutineScope
29 import kotlinx.coroutines.channels.awaitClose
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.MutableStateFlow
32 import kotlinx.coroutines.flow.SharingStarted
33 import kotlinx.coroutines.flow.stateIn
34 
35 /**
36  * Repository used for tracking the state of notification remote input (e.g. when the user presses
37  * "reply" on a notification and the keyboard opens).
38  */
39 interface RemoteInputRepository {
40     /** Whether remote input is currently active for any notification. */
41     val isRemoteInputActive: Flow<Boolean>
42 
43     /**
44      * The bottom bound of the currently focused remote input notification row, or null if there
45      * isn't one.
46      */
47     val remoteInputRowBottomBound: Flow<Float?>
48 
setRemoteInputRowBottomBoundnull49     fun setRemoteInputRowBottomBound(bottom: Float?)
50 
51     /** Close any active remote inputs */
52     fun closeRemoteInputs()
53 }
54 
55 @SysUISingleton
56 class RemoteInputRepositoryImpl
57 @Inject
58 constructor(
59     @Application applicationScope: CoroutineScope,
60     private val notificationRemoteInputManager: NotificationRemoteInputManager,
61 ) : RemoteInputRepository {
62     private val _isRemoteInputActive = conflatedCallbackFlow {
63         val callback =
64             object : RemoteInputController.Callback {
65                 override fun onRemoteInputActive(active: Boolean) {
66                     trySend(active)
67                 }
68             }
69         trySend(notificationRemoteInputManager.isRemoteInputActive)
70         notificationRemoteInputManager.addControllerCallback(callback)
71         awaitClose { notificationRemoteInputManager.removeControllerCallback(callback) }
72     }
73 
74     override val isRemoteInputActive =
75         if (SceneContainerFlag.isEnabled) {
76             _isRemoteInputActive.stateIn(
77                 applicationScope,
78                 SharingStarted.WhileSubscribed(),
79                 notificationRemoteInputManager.isRemoteInputActive,
80             )
81         } else {
82             _isRemoteInputActive
83         }
84 
85     override val remoteInputRowBottomBound = MutableStateFlow<Float?>(null)
86 
87     override fun setRemoteInputRowBottomBound(bottom: Float?) {
88         remoteInputRowBottomBound.value = bottom
89     }
90 
91     override fun closeRemoteInputs() {
92         notificationRemoteInputManager.closeRemoteInputs()
93     }
94 }
95 
96 @Module
97 interface RemoteInputRepositoryModule {
bindImplnull98     @Binds fun bindImpl(impl: RemoteInputRepositoryImpl): RemoteInputRepository
99 }
100