• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.settings.notification;
17 
18 import static android.app.NotificationManager.IMPORTANCE_NONE;
19 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
20 
21 import android.app.INotificationManager;
22 import android.app.NotificationChannel;
23 import android.app.NotificationChannelGroup;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageInfo;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ParceledListSlice;
30 import android.graphics.drawable.Drawable;
31 import android.os.ServiceManager;
32 import android.os.UserHandle;
33 import android.service.notification.NotifyingApp;
34 import android.util.IconDrawableFactory;
35 import android.util.Log;
36 
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.settingslib.Utils;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 public class NotificationBackend {
44     private static final String TAG = "NotificationBackend";
45 
46     static INotificationManager sINM = INotificationManager.Stub.asInterface(
47             ServiceManager.getService(Context.NOTIFICATION_SERVICE));
48 
loadAppRow(Context context, PackageManager pm, ApplicationInfo app)49     public AppRow loadAppRow(Context context, PackageManager pm, ApplicationInfo app) {
50         final AppRow row = new AppRow();
51         row.pkg = app.packageName;
52         row.uid = app.uid;
53         try {
54             row.label = app.loadLabel(pm);
55         } catch (Throwable t) {
56             Log.e(TAG, "Error loading application label for " + row.pkg, t);
57             row.label = row.pkg;
58         }
59         row.icon = IconDrawableFactory.newInstance(context).getBadgedIcon(app);
60         row.banned = getNotificationsBanned(row.pkg, row.uid);
61         row.showBadge = canShowBadge(row.pkg, row.uid);
62         row.userId = UserHandle.getUserId(row.uid);
63         row.blockedChannelCount = getBlockedChannelCount(row.pkg, row.uid);
64         row.channelCount = getChannelCount(row.pkg, row.uid);
65         return row;
66     }
67 
loadAppRow(Context context, PackageManager pm, PackageInfo app)68     public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) {
69         final AppRow row = loadAppRow(context, pm, app.applicationInfo);
70         recordCanBeBlocked(context, pm, app, row);
71         return row;
72     }
73 
recordCanBeBlocked(Context context, PackageManager pm, PackageInfo app, AppRow row)74     void recordCanBeBlocked(Context context, PackageManager pm, PackageInfo app, AppRow row) {
75         row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
76         final String[] nonBlockablePkgs = context.getResources().getStringArray(
77                 com.android.internal.R.array.config_nonBlockableNotificationPackages);
78         markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
79     }
80 
markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row, String packageName)81     @VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row,
82             String packageName) {
83         if (nonBlockablePkgs != null) {
84             int N = nonBlockablePkgs.length;
85             for (int i = 0; i < N; i++) {
86                 String pkg = nonBlockablePkgs[i];
87                 if (pkg == null) {
88                     continue;
89                 } else if (pkg.contains(":")) {
90                     // Interpret as channel; lock only this channel for this app.
91                     if (packageName.equals(pkg.split(":", 2)[0])) {
92                         row.lockedChannelId = pkg.split(":", 2 )[1];
93                     }
94                 } else if (packageName.equals(nonBlockablePkgs[i])) {
95                     row.systemApp = row.lockedImportance = true;
96                 }
97             }
98         }
99     }
100 
isSystemApp(Context context, ApplicationInfo app)101     public boolean isSystemApp(Context context, ApplicationInfo app) {
102         try {
103             PackageInfo info = context.getPackageManager().getPackageInfo(
104                     app.packageName, PackageManager.GET_SIGNATURES);
105             final AppRow row = new AppRow();
106             recordCanBeBlocked(context,  context.getPackageManager(), info, row);
107             return row.systemApp;
108         } catch (PackageManager.NameNotFoundException e) {
109             e.printStackTrace();
110         }
111         return false;
112     }
113 
getNotificationsBanned(String pkg, int uid)114     public boolean getNotificationsBanned(String pkg, int uid) {
115         try {
116             final boolean enabled = sINM.areNotificationsEnabledForPackage(pkg, uid);
117             return !enabled;
118         } catch (Exception e) {
119             Log.w(TAG, "Error calling NoMan", e);
120             return false;
121         }
122     }
123 
setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled)124     public boolean setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
125         try {
126             if (onlyHasDefaultChannel(pkg, uid)) {
127                 NotificationChannel defaultChannel =
128                         getChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
129                 defaultChannel.setImportance(enabled ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE);
130                 updateChannel(pkg, uid, defaultChannel);
131             }
132             sINM.setNotificationsEnabledForPackage(pkg, uid, enabled);
133             return true;
134         } catch (Exception e) {
135             Log.w(TAG, "Error calling NoMan", e);
136             return false;
137         }
138     }
139 
canShowBadge(String pkg, int uid)140     public boolean canShowBadge(String pkg, int uid) {
141         try {
142             return sINM.canShowBadge(pkg, uid);
143         } catch (Exception e) {
144             Log.w(TAG, "Error calling NoMan", e);
145             return false;
146         }
147     }
148 
setShowBadge(String pkg, int uid, boolean showBadge)149     public boolean setShowBadge(String pkg, int uid, boolean showBadge) {
150         try {
151             sINM.setShowBadge(pkg, uid, showBadge);
152             return true;
153         } catch (Exception e) {
154             Log.w(TAG, "Error calling NoMan", e);
155             return false;
156         }
157     }
158 
getChannel(String pkg, int uid, String channelId)159     public NotificationChannel getChannel(String pkg, int uid, String channelId) {
160         if (channelId == null) {
161             return null;
162         }
163         try {
164             return sINM.getNotificationChannelForPackage(pkg, uid, channelId, true);
165         } catch (Exception e) {
166             Log.w(TAG, "Error calling NoMan", e);
167             return null;
168         }
169     }
170 
getGroup(String pkg, int uid, String groupId)171     public NotificationChannelGroup getGroup(String pkg, int uid, String groupId) {
172         if (groupId == null) {
173             return null;
174         }
175         try {
176             return sINM.getNotificationChannelGroupForPackage(groupId, pkg, uid);
177         } catch (Exception e) {
178             Log.w(TAG, "Error calling NoMan", e);
179             return null;
180         }
181     }
182 
getGroups(String pkg, int uid)183     public ParceledListSlice<NotificationChannelGroup> getGroups(String pkg, int uid) {
184         try {
185             return sINM.getNotificationChannelGroupsForPackage(pkg, uid, false);
186         } catch (Exception e) {
187             Log.w(TAG, "Error calling NoMan", e);
188             return ParceledListSlice.emptyList();
189         }
190     }
191 
updateChannel(String pkg, int uid, NotificationChannel channel)192     public void updateChannel(String pkg, int uid, NotificationChannel channel) {
193         try {
194             sINM.updateNotificationChannelForPackage(pkg, uid, channel);
195         } catch (Exception e) {
196             Log.w(TAG, "Error calling NoMan", e);
197         }
198     }
199 
updateChannelGroup(String pkg, int uid, NotificationChannelGroup group)200     public void updateChannelGroup(String pkg, int uid, NotificationChannelGroup group) {
201         try {
202             sINM.updateNotificationChannelGroupForPackage(pkg, uid, group);
203         } catch (Exception e) {
204             Log.w(TAG, "Error calling NoMan", e);
205         }
206     }
207 
getDeletedChannelCount(String pkg, int uid)208     public int getDeletedChannelCount(String pkg, int uid) {
209         try {
210             return sINM.getDeletedChannelCount(pkg, uid);
211         } catch (Exception e) {
212             Log.w(TAG, "Error calling NoMan", e);
213             return 0;
214         }
215     }
216 
getBlockedChannelCount(String pkg, int uid)217     public int getBlockedChannelCount(String pkg, int uid) {
218         try {
219             return sINM.getBlockedChannelCount(pkg, uid);
220         } catch (Exception e) {
221             Log.w(TAG, "Error calling NoMan", e);
222             return 0;
223         }
224     }
225 
onlyHasDefaultChannel(String pkg, int uid)226     public boolean onlyHasDefaultChannel(String pkg, int uid) {
227         try {
228             return sINM.onlyHasDefaultChannel(pkg, uid);
229         } catch (Exception e) {
230             Log.w(TAG, "Error calling NoMan", e);
231             return false;
232         }
233     }
234 
getChannelCount(String pkg, int uid)235     public int getChannelCount(String pkg, int uid) {
236         try {
237             return sINM.getNumNotificationChannelsForPackage(pkg, uid, false);
238         } catch (Exception e) {
239             Log.w(TAG, "Error calling NoMan", e);
240             return 0;
241         }
242     }
243 
getRecentApps()244     public List<NotifyingApp> getRecentApps() {
245         try {
246             return sINM.getRecentNotifyingAppsForUser(UserHandle.myUserId()).getList();
247         } catch (Exception e) {
248             Log.w(TAG, "Error calling NoMan", e);
249             return new ArrayList<>();
250         }
251     }
252 
getBlockedAppCount()253     public int getBlockedAppCount() {
254         try {
255             return sINM.getBlockedAppCount(UserHandle.myUserId());
256         } catch (Exception e) {
257             Log.w(TAG, "Error calling NoMan", e);
258             return 0;
259         }
260     }
261 
262     static class Row {
263         public String section;
264     }
265 
266     public static class AppRow extends Row {
267         public String pkg;
268         public int uid;
269         public Drawable icon;
270         public CharSequence label;
271         public Intent settingsIntent;
272         public boolean banned;
273         public boolean first;  // first app in section
274         public boolean systemApp;
275         public boolean lockedImportance;
276         public String lockedChannelId;
277         public boolean showBadge;
278         public int userId;
279         public int blockedChannelCount;
280         public int channelCount;
281     }
282 }
283