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.any;
29 import static org.mockito.ArgumentMatchers.anyInt;
30 import static org.mockito.ArgumentMatchers.anyString;
31 import static org.mockito.Mockito.when;
32 
33 import android.app.Notification;
34 import android.app.NotificationChannel;
35 import android.app.Person;
36 import android.content.pm.ApplicationInfo;
37 import android.content.pm.PackageManager;
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 androidx.test.InstrumentationRegistry;
48 import androidx.test.runner.AndroidJUnit4;
49 
50 import org.junit.Before;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 
57 import java.util.ArrayList;
58 
59 @RunWith(AndroidJUnit4.class)
60 public class NotificationEntryTest {
61     private String mPkg = "pkg";
62     private int mUid = 2018;
63     @Mock
64     private PackageManager 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.getApplicationInfoAsUser(anyString(), anyInt(), any()))
105                 .thenReturn(mAppInfo);
106         mAppInfo.targetSdkVersion = Build.VERSION_CODES.P;
107         when(mSmsHelper.getDefaultSmsPackage()).thenReturn(DEFAULT_SMS_PACKAGE_NAME);
108     }
109 
110     @Test
testHasPerson()111     public void testHasPerson() {
112         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
113         StatusBarNotification sbn = generateSbn(channel.getId());
114         ArrayList<Person> people = new ArrayList<>();
115         people.add(new Person.Builder().setKey("mailto:testing@android.com").build());
116         sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people);
117 
118         NotificationEntry entry = new NotificationEntry(
119                 mContext, mPackageManager, sbn, channel, mSmsHelper);
120         assertTrue(entry.involvesPeople());
121     }
122 
123     @Test
testNotPerson()124     public void testNotPerson() {
125         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
126         StatusBarNotification sbn = generateSbn(channel.getId());
127         NotificationEntry entry = new NotificationEntry(
128                 mContext, mPackageManager, sbn, channel, mSmsHelper);
129         assertFalse(entry.involvesPeople());
130     }
131 
132     @Test
testHasPerson_matchesDefaultSmsApp()133     public void testHasPerson_matchesDefaultSmsApp() {
134         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
135         StatusBarNotification sbn = generateSbn(channel.getId(), DEFAULT_SMS_PACKAGE_NAME);
136         NotificationEntry entry = new NotificationEntry(
137                 mContext, mPackageManager, sbn, channel, mSmsHelper);
138         assertTrue(entry.involvesPeople());
139     }
140 
141     @Test
testHasPerson_doesntMatchDefaultSmsApp()142     public void testHasPerson_doesntMatchDefaultSmsApp() {
143         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
144         StatusBarNotification sbn = generateSbn(channel.getId(), "abc");
145         NotificationEntry entry = new NotificationEntry(
146                 mContext, mPackageManager, sbn, channel, mSmsHelper);
147         assertFalse(entry.involvesPeople());
148     }
149 
150     @Test
testIsInboxStyle()151     public void testIsInboxStyle() {
152         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
153 
154         Notification n = new Notification.Builder(mContext, channel.getId())
155                 .setStyle(new Notification.InboxStyle())
156                 .build();
157         NotificationEntry entry = new NotificationEntry(
158                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
159         assertTrue(entry.hasStyle(Notification.InboxStyle.class));
160     }
161 
162     @Test
testIsMessagingStyle()163     public void testIsMessagingStyle() {
164         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
165 
166         Notification n = new Notification.Builder(mContext, channel.getId())
167                 .setStyle(new Notification.MessagingStyle(""))
168                 .build();
169         NotificationEntry entry = new NotificationEntry(
170                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
171         assertTrue(entry.hasStyle(Notification.MessagingStyle.class));
172     }
173 
174     @Test
testIsNotPersonStyle()175     public void testIsNotPersonStyle() {
176         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
177 
178         Notification n = new Notification.Builder(mContext, channel.getId())
179                 .setStyle(new Notification.BigPictureStyle())
180                 .build();
181         NotificationEntry entry = new NotificationEntry(
182                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
183         assertFalse(entry.hasStyle(Notification.InboxStyle.class));
184         assertFalse(entry.hasStyle(Notification.MessagingStyle.class));
185     }
186 
187     @Test
testIsAudioAttributes()188     public void testIsAudioAttributes() {
189         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
190         channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());
191 
192         NotificationEntry entry = new NotificationEntry(
193                 mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
194 
195         assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM));
196     }
197 
198     @Test
testIsNotAudioAttributes()199     public void testIsNotAudioAttributes() {
200         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
201         NotificationEntry entry = new NotificationEntry(
202                 mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
203 
204         assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM));
205     }
206 
207     @Test
testIsCategory()208     public void testIsCategory() {
209         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
210 
211         Notification n = new Notification.Builder(mContext, channel.getId())
212                 .setCategory(Notification.CATEGORY_EMAIL)
213                 .build();
214         NotificationEntry entry = new NotificationEntry(
215                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
216 
217         assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL));
218         assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE));
219     }
220 
221     @Test
testIsOngoing()222     public void testIsOngoing() {
223         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
224 
225         Notification n = new Notification.Builder(mContext, channel.getId())
226                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
227                 .build();
228         NotificationEntry entry = new NotificationEntry(
229                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
230 
231         assertTrue(entry.isOngoing());
232     }
233 
234     @Test
testIsNotOngoing()235     public void testIsNotOngoing() {
236         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
237 
238         Notification n = new Notification.Builder(mContext, channel.getId())
239                 .setFlag(FLAG_CAN_COLORIZE, true)
240                 .build();
241         NotificationEntry entry = new NotificationEntry(
242                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
243 
244         assertFalse(entry.isOngoing());
245     }
246 
247     @Test
testShrinkNotification()248     public void testShrinkNotification() {
249         Notification n = new Notification.Builder(mContext, "")
250                 .setLargeIcon(Icon.createWithResource(
251                         mContext, android.R.drawable.alert_dark_frame))
252                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
253                 .build();
254         n.largeIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
255         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
256 
257         NotificationEntry entry = new NotificationEntry(
258                 mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
259 
260         assertNull(entry.getNotification().getSmallIcon());
261         assertNull(entry.getNotification().getLargeIcon());
262         assertNull(entry.getNotification().largeIcon);
263         assertNull(entry.getNotification().extras.getParcelable(Notification.EXTRA_LARGE_ICON));
264     }
265 }
266