1 /*
2  * Copyright (C) 2020 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.settings.notification.history;
18 
19 import android.app.NotificationHistory;
20 import android.app.NotificationHistory.HistoricalNotification;
21 import android.content.Context;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.os.UserHandle;
25 import android.util.Slog;
26 
27 import com.android.settings.notification.NotificationBackend;
28 import com.android.settingslib.utils.ThreadUtils;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 
36 public class HistoryLoader {
37     private static final String TAG = "HistoryLoader";
38     private final Context mContext;
39     private final NotificationBackend mBackend;
40     private final PackageManager mPm;
41 
HistoryLoader(Context context, NotificationBackend backend, PackageManager pm)42     public HistoryLoader(Context context, NotificationBackend backend, PackageManager pm) {
43         mContext = context;
44         mBackend = backend;
45         mPm = pm;
46     }
47 
load(OnHistoryLoaderListener listener)48     public void load(OnHistoryLoaderListener listener) {
49         ThreadUtils.postOnBackgroundThread(() -> {
50             try {
51                 Map<String, NotificationHistoryPackage> historicalNotifications = new HashMap<>();
52                 NotificationHistory history =
53                         mBackend.getNotificationHistory(mContext.getPackageName(),
54                                 mContext.getAttributionTag());
55                 while (history.hasNextNotification()) {
56                     HistoricalNotification hn = history.getNextNotification();
57 
58                     String key = hn.getPackage() + "|" + hn.getUid();
59                     NotificationHistoryPackage hnsForPackage = historicalNotifications.getOrDefault(
60                             key,
61                             new NotificationHistoryPackage(hn.getPackage(), hn.getUid()));
62                     hnsForPackage.notifications.add(hn);
63                     historicalNotifications.put(key, hnsForPackage);
64                 }
65                 List<NotificationHistoryPackage> packages =
66                         new ArrayList<>(historicalNotifications.values());
67                 Collections.sort(packages,
68                         (o1, o2) -> -1 * Long.compare(o1.getMostRecent(), o2.getMostRecent()));
69                 for (NotificationHistoryPackage nhp : packages) {
70                     ApplicationInfo info;
71                     try {
72                         info = mPm.getApplicationInfoAsUser(
73                                 nhp.pkgName,
74                                 PackageManager.MATCH_UNINSTALLED_PACKAGES
75                                         | PackageManager.MATCH_DISABLED_COMPONENTS
76                                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
77                                         | PackageManager.MATCH_DIRECT_BOOT_AWARE,
78                                 UserHandle.getUserId(nhp.uid));
79                         if (info != null) {
80                             nhp.label = String.valueOf(mPm.getApplicationLabel(info));
81                             nhp.icon = mPm.getUserBadgedIcon(mPm.getApplicationIcon(info),
82                                     UserHandle.of(UserHandle.getUserId(nhp.uid)));
83                         }
84                     } catch (PackageManager.NameNotFoundException e) {
85                         // app is gone, just show package name and generic icon
86                         nhp.icon = mPm.getDefaultActivityIcon();
87                     }
88                 }
89                 ThreadUtils.postOnMainThread(() -> listener.onHistoryLoaded(packages));
90             } catch (Exception e) {
91                 Slog.e(TAG, "Error loading history", e);
92             }
93         });
94     }
95 
96     interface OnHistoryLoaderListener {
onHistoryLoaded(List<NotificationHistoryPackage> notificationsByPackage)97         void onHistoryLoaded(List<NotificationHistoryPackage> notificationsByPackage);
98     }
99 }
100