1 /**
2  * Copyright (C) 2018 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 android.ext.services.notification;
17 
18 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
19 import static android.app.NotificationManager.IMPORTANCE_HIGH;
20 import static android.app.NotificationManager.IMPORTANCE_MIN;
21 
22 import android.annotation.IntDef;
23 import android.app.Notification;
24 import android.media.AudioAttributes;
25 import android.os.Process;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 
32 /**
33  * Default categorizer for incoming notifications; used to determine what notifications
34  * should be silenced.
35  */
36 // TODO: stop using @hide methods
37 public class NotificationCategorizer {
38 
39     protected static final int CATEGORY_MIN = -3;
40     protected static final int CATEGORY_EVERYTHING_ELSE = -2;
41     protected static final int CATEGORY_ONGOING = -1;
42     protected static final int CATEGORY_SYSTEM_LOW = 0;
43     protected static final int CATEGORY_EVENT = 1;
44     protected static final int CATEGORY_REMINDER = 2;
45     protected static final int CATEGORY_SYSTEM = 3;
46     protected static final int CATEGORY_PEOPLE = 4;
47     protected static final int CATEGORY_ALARM = 5;
48     protected static final int CATEGORY_CALL = 6;
49     protected static final int CATEGORY_HIGH = 7;
50 
51     /** @hide */
52     @IntDef(prefix = { "CATEGORY_" }, value = {
53             CATEGORY_MIN, CATEGORY_EVERYTHING_ELSE, CATEGORY_ONGOING, CATEGORY_CALL,
54             CATEGORY_SYSTEM_LOW, CATEGORY_EVENT, CATEGORY_REMINDER, CATEGORY_SYSTEM,
55             CATEGORY_PEOPLE, CATEGORY_ALARM, CATEGORY_HIGH
56     })
57     @Retention(RetentionPolicy.SOURCE)
58     public @interface Category {}
59 
shouldSilence(NotificationEntry entry)60     public boolean shouldSilence(NotificationEntry entry) {
61         return shouldSilence(getCategory(entry));
62     }
63 
64     @VisibleForTesting
shouldSilence(int category)65     boolean shouldSilence(int category) {
66         return category < CATEGORY_EVENT;
67     }
68 
getCategory(NotificationEntry entry)69     public int getCategory(NotificationEntry entry) {
70         if (entry.getChannel() == null) {
71             return CATEGORY_EVERYTHING_ELSE;
72         }
73         if (entry.getChannel().getImportance() == IMPORTANCE_MIN) {
74             return CATEGORY_MIN;
75         }
76         if (entry.isCategory(Notification.CATEGORY_REMINDER)) {
77             return CATEGORY_REMINDER;
78         }
79         if (entry.isCategory(Notification.CATEGORY_EVENT)) {
80             return CATEGORY_EVENT;
81         }
82         if (entry.isCategory(Notification.CATEGORY_ALARM)
83                 || entry.isAudioAttributesUsage(AudioAttributes.USAGE_ALARM)) {
84             return CATEGORY_ALARM;
85         }
86         // TODO: check for default phone app
87         if (entry.isCategory(Notification.CATEGORY_CALL)) {
88             return CATEGORY_CALL;
89         }
90         if (entry.involvesPeople()) {
91             return CATEGORY_PEOPLE;
92         }
93         // TODO: is from signature app
94         if (entry.getSbn().getUid() < Process.FIRST_APPLICATION_UID) {
95             if (entry.getImportance() >= IMPORTANCE_DEFAULT) {
96                 return CATEGORY_SYSTEM;
97             } else {
98                 return CATEGORY_SYSTEM_LOW;
99             }
100         }
101         if (entry.getChannel().getImportance() == IMPORTANCE_HIGH) {
102             return CATEGORY_HIGH;
103         }
104         if (entry.isOngoing()) {
105             return CATEGORY_ONGOING;
106         }
107         return CATEGORY_EVERYTHING_ELSE;
108     }
109 }
110