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