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.providers.media.photopicker.sync;
18 
19 import android.app.Notification;
20 import android.app.NotificationChannel;
21 import android.app.NotificationManager;
22 import android.content.Context;
23 import android.content.res.Resources;
24 import android.util.Log;
25 
26 import androidx.annotation.NonNull;
27 import androidx.annotation.VisibleForTesting;
28 import androidx.core.app.NotificationCompat;
29 import androidx.work.ForegroundInfo;
30 
31 import com.android.modules.utils.build.SdkLevel;
32 import com.android.providers.media.R;
33 
34 /**
35  * Helper functions for Picker sync notifications.
36  */
37 public class PickerSyncNotificationHelper {
38     private static final String TAG = "SyncNotifHelper";
39     @VisibleForTesting
40     static final String NOTIFICATION_CHANNEL_ID = "PhotoPickerSyncChannel";
41     @VisibleForTesting
42     static final int NOTIFICATION_ID = 0;
43     private static final int NOTIFICATION_TIMEOUT_MILLIS = 1000;
44 
45 
46     /**
47      * Created notification channel for Picker Sync notifications.
48      * Recreating an existing notification channel with its original values performs no operation,
49      * so it's safe to call this code when starting an app.
50      */
createNotificationChannel(@onNull Context context)51     public static void createNotificationChannel(@NonNull Context context) {
52         final String contentTitle = context.getResources()
53                 .getString(R.string.picker_sync_notification_channel);
54 
55         final NotificationChannel channel = new NotificationChannel(
56                 NOTIFICATION_CHANNEL_ID, contentTitle, NotificationManager.IMPORTANCE_LOW);
57         channel.enableLights(false);
58         channel.enableVibration(false);
59 
60         final NotificationManager notificationManager =
61                 context.getSystemService(NotificationManager.class);
62         if (notificationManager != null) {
63             notificationManager.createNotificationChannel(channel);
64         }
65     }
66 
67     /**
68      * Return Foreground info. This object contains a Notification and notification id that should
69      * be displayed in the context of a foreground service.
70      * This method should not be invoked by WorkManager in Android S+ devices.
71      */
72     @NonNull
getForegroundInfo(@onNull Context context)73     public static ForegroundInfo getForegroundInfo(@NonNull Context context) {
74         if (SdkLevel.isAtLeastS()) {
75             Log.w(TAG, "Picker Sync notifications should not be displayed in S+ devices.");
76         }
77         return new ForegroundInfo(NOTIFICATION_ID, getNotification(context));
78     }
79 
80     /**
81      * Create a notification to display when Picker sync is happening.
82      */
getNotification(@onNull Context context)83     private static Notification getNotification(@NonNull Context context) {
84         final Resources resources = context.getResources();
85         final String contentTitle = resources.getString(R.string.picker_sync_notification_title);
86         final String contentText = resources.getString(R.string.picker_sync_notification_text);
87 
88         return new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
89                 .setSmallIcon(R.drawable.picker_app_icon)
90                 .setContentTitle(contentTitle)
91                 .setContentText(contentText)
92                 .setPriority(NotificationCompat.PRIORITY_MIN)
93                 .setVisibility(NotificationCompat.VISIBILITY_SECRET)
94                 .setSilent(true)
95                 .setTimeoutAfter(NOTIFICATION_TIMEOUT_MILLIS)
96                 .build();
97     }
98 }
99