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.mediaprojection.taskswitcher.ui
18 
19 import android.app.Notification
20 import android.app.NotificationChannel
21 import android.app.NotificationManager
22 import android.content.Context
23 import android.util.Log
24 import com.android.systemui.R
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Application
27 import com.android.systemui.dagger.qualifiers.Main
28 import com.android.systemui.mediaprojection.taskswitcher.ui.model.TaskSwitcherNotificationUiState.NotShowing
29 import com.android.systemui.mediaprojection.taskswitcher.ui.model.TaskSwitcherNotificationUiState.Showing
30 import com.android.systemui.mediaprojection.taskswitcher.ui.viewmodel.TaskSwitcherNotificationViewModel
31 import com.android.systemui.util.NotificationChannels
32 import javax.inject.Inject
33 import kotlinx.coroutines.CoroutineDispatcher
34 import kotlinx.coroutines.CoroutineScope
35 import kotlinx.coroutines.flow.flowOn
36 import kotlinx.coroutines.launch
37 
38 /** Coordinator responsible for showing/hiding the task switcher notification. */
39 @SysUISingleton
40 class TaskSwitcherNotificationCoordinator
41 @Inject
42 constructor(
43     private val context: Context,
44     private val notificationManager: NotificationManager,
45     @Application private val applicationScope: CoroutineScope,
46     @Main private val mainDispatcher: CoroutineDispatcher,
47     private val viewModel: TaskSwitcherNotificationViewModel,
48 ) {
49     fun start() {
50         applicationScope.launch {
51             viewModel.uiState.flowOn(mainDispatcher).collect { uiState ->
52                 Log.d(TAG, "uiState -> $uiState")
53                 when (uiState) {
54                     is Showing -> showNotification()
55                     is NotShowing -> hideNotification()
56                 }
57             }
58         }
59     }
60 
61     private fun showNotification() {
62         notificationManager.notify(TAG, NOTIFICATION_ID, createNotification())
63     }
64 
65     private fun createNotification(): Notification {
66         // TODO(b/286201261): implement actions
67         val actionSwitch =
68             Notification.Action.Builder(
69                     /* icon = */ null,
70                     context.getString(R.string.media_projection_task_switcher_action_switch),
71                     /* intent = */ null
72                 )
73                 .build()
74 
75         val actionBack =
76             Notification.Action.Builder(
77                     /* icon = */ null,
78                     context.getString(R.string.media_projection_task_switcher_action_back),
79                     /* intent = */ null
80                 )
81                 .build()
82 
83         val channel =
84             NotificationChannel(
85                 NotificationChannels.HINTS,
86                 context.getString(R.string.media_projection_task_switcher_notification_channel),
87                 NotificationManager.IMPORTANCE_HIGH
88             )
89         notificationManager.createNotificationChannel(channel)
90         return Notification.Builder(context, channel.id)
91             .setSmallIcon(R.drawable.qs_screen_record_icon_on)
92             .setAutoCancel(true)
93             .setContentText(context.getString(R.string.media_projection_task_switcher_text))
94             .addAction(actionSwitch)
95             .addAction(actionBack)
96             .setPriority(Notification.PRIORITY_HIGH)
97             .setDefaults(Notification.DEFAULT_VIBRATE)
98             .build()
99     }
100 
101     private fun hideNotification() {
102         notificationManager.cancel(NOTIFICATION_ID)
103     }
104 
105     companion object {
106         private const val TAG = "TaskSwitchNotifCoord"
107         private const val NOTIFICATION_ID = 5566
108     }
109 }
110