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 
17 package android.ext.services.notification;
18 
19 import static android.app.Notification.FLAG_CAN_COLORIZE;
20 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
21 import static android.app.NotificationManager.IMPORTANCE_HIGH;
22 import static android.media.AudioAttributes.USAGE_ALARM;
23 
24 import static junit.framework.Assert.assertFalse;
25 import static junit.framework.Assert.assertTrue;
26 
27 import static org.junit.Assert.assertNull;
28 import static org.mockito.ArgumentMatchers.anyInt;
29 import static org.mockito.ArgumentMatchers.anyString;
30 import static org.mockito.Mockito.when;
31 
32 import android.app.Notification;
33 import android.app.NotificationChannel;
34 import android.app.Person;
35 import android.content.ComponentName;
36 import android.content.pm.ApplicationInfo;
37 import android.content.pm.IPackageManager;
38 import android.graphics.Bitmap;
39 import android.graphics.drawable.Icon;
40 import android.media.AudioAttributes;
41 import android.os.Build;
42 import android.os.Process;
43 import android.os.UserHandle;
44 import android.service.notification.StatusBarNotification;
45 import android.testing.TestableContext;
46 
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.Mock;
52 import org.mockito.MockitoAnnotations;
53 
54 import java.util.ArrayList;
55 
56 import androidx.test.InstrumentationRegistry;
57 import androidx.test.runner.AndroidJUnit4;
58 
59 @RunWith(AndroidJUnit4.class)
60 public class NotificationEntryTest {
61     private String mPkg = "pkg";
62     private int mUid = 2018;
63     @Mock
64     private IPackageManager mPackageManager;
65     @Mock
66     private ApplicationInfo mAppInfo;
67     @Mock
68     private SmsHelper mSmsHelper;
69 
70     private static final String DEFAULT_SMS_PACKAGE_NAME = "foo";
71 
72     @Rule
73     public final TestableContext mContext =
74             new TestableContext(InstrumentationRegistry.getContext(), null);
75 
generateSbn(String channelId)76     private StatusBarNotification generateSbn(String channelId) {
77         Notification n = new Notification.Builder(mContext, channelId)
78                 .setContentTitle("foo")
79                 .build();
80 
81         return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n,
82                 UserHandle.SYSTEM, null, 0);
83     }
84 
generateSbn(String channelId, String packageName)85     private StatusBarNotification generateSbn(String channelId, String packageName) {
86         Notification n = new Notification.Builder(mContext, channelId)
87                 .setContentTitle("foo")
88                 .build();
89 
90         return new StatusBarNotification(packageName, packageName, 0, "tag", mUid, mUid, n,
91                 UserHandle.SYSTEM, null, 0);
92     }
93 
generateSbn(Notification n)94     private StatusBarNotification generateSbn(Notification n) {
95         return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n,
96                 UserHandle.SYSTEM, null, 0);
97     }
98 
99     @Before
setUp()100     public void setUp() throws Exception {
101         MockitoAnnotations.initMocks(this);
102         mPkg = mContext.getPackageName();
103         mUid = Process.myUid();
104         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
105                 .thenReturn(mAppInfo);
106         mAppInfo.targetSdkVersion = Build.VERSION_CODES.P;
107         when(mSmsHelper.getDefaultSmsApplication())
108                 .thenReturn(new ComponentName(DEFAULT_SMS_PACKAGE_NAME, "bar"));
109     }
110 
111     @Test
testHasPerson()112     public void testHasPerson() {
113         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
114         StatusBarNotification sbn = generateSbn(channel.getId());
115         ArrayList<Person> people = new ArrayList<>();
116         people.add(new Person.Builder().setKey("mailto:testing@android.com").build());
117         sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people);
118 
119         NotificationEntry entry = new NotificationEntry(
120                 mContext, mPackageManager, sbn, channel, mSmsHelper);
121         assertTrue(entry.involvesPeople());
122     }
123 
124     @Test
testNotPerson()125     public void testNotPerson() {
126         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
127         StatusBarNotification sbn = generateSbn(channel.getId());
128         NotificationEntry entry = new NotificationEntry(
129                 mContext, mPackageManager, sbn, channel, mSmsHelper);
130         assertFalse(entry.involvesPeople());
131     }
132 
133     @Test
testHasPerson_matchesDefaultSmsApp()134     public void testHasPerson_matchesDefaultSmsApp() {
135         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
136         StatusBarNotification sbn = generateSbn(channel.getId(), DEFAULT_SMS_PACKAGE_NAME);
137         NotificationEntry entry = new NotificationEntry(
138                 mContext, mPackageManager, sbn, channel, mSmsHelper);
139         assertTrue(entry.involvesPeople());
140     }
141 
142     @Test
testHasPerson_doesntMatchDefaultSmsApp()143     public void testHasPerson_doesntMatchDefaultSmsApp() {
144         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
145         StatusBarNotification sbn = generateSbn(channel.getId(), "abc");
146         NotificationEntry entry = new NotificationEntry(
147                 mContext, mPackageManager, sbn, channel, mSmsHelper);
148         assertFalse(entry.involvesPeople());
149     }
150 
151     @Test
testIsInboxStyle()152     public void testIsInboxStyle() {
153         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
154 
155         Notification n = new Notification.Builder(mContext, channel.getId())
156                 .setStyle(new Notification.InboxStyle())
157                 .build();
158         NotificationEntry entry = new NotificationEntry(
159                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
160         assertTrue(entry.hasStyle(Notification.InboxStyle.class));
161     }
162 
163     @Test
testIsMessagingStyle()164     public void testIsMessagingStyle() {
165         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
166 
167         Notification n = new Notification.Builder(mContext, channel.getId())
168                 .setStyle(new Notification.MessagingStyle(""))
169                 .build();
170         NotificationEntry entry = new NotificationEntry(
171                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
172         assertTrue(entry.hasStyle(Notification.MessagingStyle.class));
173     }
174 
175     @Test
testIsNotPersonStyle()176     public void testIsNotPersonStyle() {
177         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
178 
179         Notification n = new Notification.Builder(mContext, channel.getId())
180                 .setStyle(new Notification.BigPictureStyle())
181                 .build();
182         NotificationEntry entry = new NotificationEntry(
183                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
184         assertFalse(entry.hasStyle(Notification.InboxStyle.class));
185         assertFalse(entry.hasStyle(Notification.MessagingStyle.class));
186     }
187 
188     @Test
testIsAudioAttributes()189     public void testIsAudioAttributes() {
190         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
191         channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());
192 
193         NotificationEntry entry = new NotificationEntry(
194                 mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
195 
196         assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM));
197     }
198 
199     @Test
testIsNotAudioAttributes()200     public void testIsNotAudioAttributes() {
201         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
202         NotificationEntry entry = new NotificationEntry(
203                 mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
204 
205         assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM));
206     }
207 
208     @Test
testIsCategory()209     public void testIsCategory() {
210         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
211 
212         Notification n = new Notification.Builder(mContext, channel.getId())
213                 .setCategory(Notification.CATEGORY_EMAIL)
214                 .build();
215         NotificationEntry entry = new NotificationEntry(
216                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
217 
218         assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL));
219         assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE));
220     }
221 
222     @Test
testIsOngoing()223     public void testIsOngoing() {
224         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
225 
226         Notification n = new Notification.Builder(mContext, channel.getId())
227                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
228                 .build();
229         NotificationEntry entry = new NotificationEntry(
230                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
231 
232         assertTrue(entry.isOngoing());
233     }
234 
235     @Test
testIsNotOngoing()236     public void testIsNotOngoing() {
237         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
238 
239         Notification n = new Notification.Builder(mContext, channel.getId())
240                 .setFlag(FLAG_CAN_COLORIZE, true)
241                 .build();
242         NotificationEntry entry = new NotificationEntry(
243                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
244 
245         assertFalse(entry.isOngoing());
246     }
247 
248     @Test
testShrinkNotification()249     public void testShrinkNotification() {
250         Notification n = new Notification.Builder(mContext, "")
251                 .setLargeIcon(Icon.createWithResource(
252                         mContext, android.R.drawable.alert_dark_frame))
253                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
254                 .build();
255         n.largeIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
256         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
257 
258         NotificationEntry entry = new NotificationEntry(
259                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
260 
261         assertNull(entry.getNotification().getSmallIcon());
262         assertNull(entry.getNotification().getLargeIcon());
263         assertNull(entry.getNotification().largeIcon);
264         assertNull(entry.getNotification().extras.getParcelable(Notification.EXTRA_LARGE_ICON));
265     }
266 }
267