• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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.privatespace.filetransfer
18 
19 import android.app.DownloadManager
20 import android.app.Notification
21 import android.app.NotificationChannel
22 import android.app.NotificationManager
23 import android.app.PendingIntent
24 import android.content.Context
25 import android.content.Intent
26 import com.android.privatespace.R
27 import java.util.concurrent.atomic.AtomicBoolean
28 
29 /** A helper class to send file transfer progress and completion notifications to the user */
30 class NotificationsHelper(private val context: Context) {
31 
32     companion object {
33         private val NOTIFICATION_CHANNEL_ID: String = "FileTransferProgress"
34         const val NOTIFICATION_ID: Int = 1
35     }
36 
37     private var canUpdateProgressNotification = AtomicBoolean(true)
38 
39     private var notificationManager: NotificationManager =
40         context.getSystemService(NotificationManager::class.java)
41 
createNotificationChannelnull42     fun createNotificationChannel() {
43         val channel =
44             NotificationChannel(
45                 NOTIFICATION_CHANNEL_ID,
46                 context.getString(R.string.filetransfer_notification_channel_name),
47                 NotificationManager.IMPORTANCE_HIGH,
48             )
49         channel.description =
50             context.getString(R.string.filetransfer_notification_channel_description)
51         notificationManager.createNotificationChannel(channel)
52     }
53 
displayCompletionNotificationnull54     fun displayCompletionNotification(numberOfFiles: Int, keepOriginal: Boolean) {
55         canUpdateProgressNotification.getAndSet(false)
56         val notification = buildCompletionNotification(numberOfFiles, keepOriginal)
57         notificationManager.notify(NOTIFICATION_ID, notification)
58     }
59 
updateProgressNotificationnull60     fun updateProgressNotification(progress: Int, numberOfFiles: Int, keepOriginal: Boolean) {
61         val notification = buildProgressNotification(progress, numberOfFiles, keepOriginal)
62         if (canUpdateProgressNotification.acquire) {
63             notificationManager.notify(NOTIFICATION_ID, notification)
64         }
65     }
66 
buildProgressNotificationnull67     fun buildProgressNotification(
68         progress: Int,
69         numberOfFiles: Int,
70         keepOriginal: Boolean,
71     ): Notification {
72         val openFileIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
73         openFileIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
74 
75         val notificationTitle =
76             context.resources.getString(
77                 if (keepOriginal) R.string.filetransfer_notification_copy_progress_title
78                 else R.string.filetransfer_notification_move_progress_title,
79                 numberOfFiles,
80             )
81         val notificationText =
82             context
83                 .getResources()
84                 .getString(
85                     if (keepOriginal) R.string.filetransfer_notification_copy_progress_text
86                     else R.string.filetransfer_notification_move_progress_text
87                 )
88 
89         val pendingIntent =
90             PendingIntent.getActivity(
91                 context,
92                 0,
93                 openFileIntent,
94                 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
95             )
96 
97         return baseNotificationBuilder(notificationTitle, notificationText, context)
98             .setOngoing(true)
99             .setProgress(100, progress, false)
100             .setContentIntent(pendingIntent)
101             .addAction(
102                 Notification.Action.Builder(
103                         R.drawable.ic_private_profile_badge,
104                         context.resources.getString(
105                             R.string.filetransfer_notification_action_label
106                         ),
107                         pendingIntent,
108                     )
109                     .build()
110             )
111             .build()
112     }
113 
buildCompletionNotificationnull114     private fun buildCompletionNotification(
115         numberOfFiles: Int,
116         keepOriginal: Boolean,
117     ): Notification {
118         val openFileIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
119         openFileIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
120 
121         val notificationTitle =
122             context.resources.getString(
123                 if (keepOriginal) R.string.filetransfer_notification_copy_complete_title
124                 else R.string.filetransfer_notification_move_complete_title,
125                 numberOfFiles,
126             )
127         val notificationText =
128             context.resources.getString(
129                 if (keepOriginal) R.string.filetransfer_notification_copy_complete_text
130                 else R.string.filetransfer_notification_move_complete_text
131             )
132 
133         val pendingIntent =
134             PendingIntent.getActivity(
135                 context,
136                 0,
137                 openFileIntent,
138                 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
139             )
140 
141         return baseNotificationBuilder(notificationTitle, notificationText, context)
142             .setOngoing(false)
143             .setContentIntent(pendingIntent)
144             .setAutoCancel(true)
145             .addAction(
146                 Notification.Action.Builder(
147                         R.drawable.ic_private_profile_badge,
148                         context.resources.getString(
149                             R.string.filetransfer_notification_action_label
150                         ),
151                         pendingIntent,
152                     )
153                     .build()
154             )
155             .build()
156     }
157 
baseNotificationBuildernull158     private fun baseNotificationBuilder(
159         contentTitle: String,
160         contentText: String,
161         context: Context,
162     ): Notification.Builder {
163         return Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
164             .setContentTitle(contentTitle)
165             .setContentText(contentText)
166             .setSmallIcon(R.drawable.ic_private_profile_badge)
167             .setOnlyAlertOnce(true)
168     }
169 }
170