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