1/*
2 * Copyright (C) 2016 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 */
16package com.android.server.notification;
17
18import static org.junit.Assert.assertEquals;
19import static org.junit.Assert.assertFalse;
20import static org.junit.Assert.assertTrue;
21import static org.mockito.Matchers.anyInt;
22import static org.mockito.Matchers.anyString;
23import static org.mockito.Matchers.eq;
24import static org.mockito.Mockito.when;
25
26import android.app.Notification;
27import android.app.NotificationChannel;
28import android.app.NotificationManager;
29import android.content.Context;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.media.session.MediaSession;
33import android.os.Build;
34import android.os.UserHandle;
35import android.provider.Settings;
36import android.service.notification.StatusBarNotification;
37import android.telecom.TelecomManager;
38import android.support.test.runner.AndroidJUnit4;
39import android.test.suitebuilder.annotation.SmallTest;
40
41import org.junit.Before;
42import org.junit.Test;
43import org.junit.runner.RunWith;
44import org.mockito.Mock;
45import org.mockito.MockitoAnnotations;
46
47import java.util.ArrayList;
48import java.util.Collections;
49import java.util.List;
50
51@SmallTest
52@RunWith(AndroidJUnit4.class)
53public class NotificationComparatorTest extends NotificationTestCase {
54    @Mock Context mContext;
55    @Mock TelecomManager mTm;
56    @Mock RankingHandler handler;
57    @Mock PackageManager mPm;
58
59    private final String callPkg = "com.android.server.notification";
60    private final int callUid = 10;
61    private String smsPkg;
62    private final int smsUid = 11;
63    private final String pkg2 = "pkg2";
64    private final int uid2 = 1111111;
65    private static final String TEST_CHANNEL_ID = "test_channel_id";
66
67    private NotificationRecord mRecordMinCall;
68    private NotificationRecord mRecordHighCall;
69    private NotificationRecord mRecordDefaultMedia;
70    private NotificationRecord mRecordEmail;
71    private NotificationRecord mRecordInlineReply;
72    private NotificationRecord mRecordSms;
73    private NotificationRecord mRecordStarredContact;
74    private NotificationRecord mRecordContact;
75    private NotificationRecord mRecordUrgent;
76    private NotificationRecord mRecordCheater;
77    private NotificationRecord mRecordCheaterColorized;
78    private NotificationRecord mNoMediaSessionMedia;
79
80    @Before
81    public void setUp() {
82        MockitoAnnotations.initMocks(this);
83        int userId = UserHandle.myUserId();
84
85        when(mContext.getResources()).thenReturn(getContext().getResources());
86        when(mContext.getContentResolver()).thenReturn(getContext().getContentResolver());
87        when(mContext.getPackageManager()).thenReturn(mPm);
88        when(mContext.getSystemService(eq(Context.TELECOM_SERVICE))).thenReturn(mTm);
89        when(mTm.getDefaultDialerPackage()).thenReturn(callPkg);
90        final ApplicationInfo legacy = new ApplicationInfo();
91        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
92        try {
93            when(mPm.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())).thenReturn(legacy);
94            when(mContext.getApplicationInfo()).thenReturn(legacy);
95        } catch (PackageManager.NameNotFoundException e) {
96            // let's hope not
97        }
98
99        smsPkg = Settings.Secure.getString(mContext.getContentResolver(),
100                Settings.Secure.SMS_DEFAULT_APPLICATION);
101
102        Notification n1 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
103                .setCategory(Notification.CATEGORY_CALL)
104                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
105                .build();
106        mRecordMinCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
107                callPkg, 1, "minCall", callUid, callUid, n1,
108                new UserHandle(userId), "", 2000), getDefaultChannel());
109        mRecordMinCall.setUserImportance(NotificationManager.IMPORTANCE_MIN);
110
111        Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
112                .setCategory(Notification.CATEGORY_CALL)
113                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
114                .setColorized(true /* colorized */)
115                .build();
116        mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
117                callPkg, 1, "highcall", callUid, callUid, n2,
118                new UserHandle(userId), "", 1999), getDefaultChannel());
119        mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
120
121        Notification n3 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
122                .setStyle(new Notification.MediaStyle()
123                        .setMediaSession(new MediaSession.Token(null)))
124                .build();
125        mRecordDefaultMedia = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
126                pkg2, 1, "media", uid2, uid2, n3, new UserHandle(userId),
127                "", 1499), getDefaultChannel());
128        mRecordDefaultMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
129
130        Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
131                .setStyle(new Notification.MessagingStyle("sender!")).build();
132        mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
133                pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
134                "", 1599), getDefaultChannel());
135        mRecordInlineReply.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
136        mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
137
138        Notification n5 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
139                .setCategory(Notification.CATEGORY_MESSAGE).build();
140        mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
141                smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
142                "", 1299), getDefaultChannel());
143        mRecordSms.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
144
145        Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
146        mRecordStarredContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
147                pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
148                "", 1259), getDefaultChannel());
149        mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
150        mRecordStarredContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
151
152        Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
153        mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
154                pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
155                "", 1259), getDefaultChannel());
156        mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
157        mRecordContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
158
159        Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
160        mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
161                pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
162                "", 1258), getDefaultChannel());
163        mRecordUrgent.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
164
165        Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
166                .setCategory(Notification.CATEGORY_MESSAGE)
167                .setFlag(Notification.FLAG_ONGOING_EVENT
168                        |Notification.FLAG_FOREGROUND_SERVICE, true)
169                .build();
170        mRecordCheater = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
171                pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
172                "", 9258), getDefaultChannel());
173        mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
174        mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
175
176        Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
177                .setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
178        mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
179                pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
180                "", 1599), getDefaultChannel());
181        mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
182
183        Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
184                .setCategory(Notification.CATEGORY_MESSAGE)
185                .setColorized(true)
186                .build();
187        mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
188                pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
189                "", 9258), getDefaultChannel());
190        mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
191
192        Notification n12 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
193                .setCategory(Notification.CATEGORY_MESSAGE)
194                .setColorized(true)
195                .setStyle(new Notification.MediaStyle())
196                .build();
197        mNoMediaSessionMedia = new NotificationRecord(mContext, new StatusBarNotification(
198                pkg2, pkg2, 1, "cheater", uid2, uid2, n12, new UserHandle(userId),
199                "", 9258), getDefaultChannel());
200        mNoMediaSessionMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
201    }
202
203    @Test
204    public void testOrdering() throws Exception {
205        final List<NotificationRecord> expected = new ArrayList<>();
206        expected.add(mRecordHighCall);
207        expected.add(mRecordDefaultMedia);
208        expected.add(mRecordInlineReply);
209        expected.add(mRecordSms);
210        expected.add(mRecordStarredContact);
211        expected.add(mRecordContact);
212        expected.add(mRecordEmail);
213        expected.add(mRecordUrgent);
214        expected.add(mNoMediaSessionMedia);
215        expected.add(mRecordCheater);
216        expected.add(mRecordCheaterColorized);
217        expected.add(mRecordMinCall);
218
219        List<NotificationRecord> actual = new ArrayList<>();
220        actual.addAll(expected);
221        Collections.shuffle(actual);
222
223        Collections.sort(actual, new NotificationComparator(mContext));
224
225        assertEquals(expected, actual);
226    }
227
228    @Test
229    public void testMessaging() throws Exception {
230        NotificationComparator comp = new NotificationComparator(mContext);
231        assertTrue(comp.isImportantMessaging(mRecordInlineReply));
232        assertTrue(comp.isImportantMessaging(mRecordSms));
233        assertFalse(comp.isImportantMessaging(mRecordEmail));
234        assertFalse(comp.isImportantMessaging(mRecordCheater));
235    }
236
237    @Test
238    public void testPeople() throws Exception {
239        NotificationComparator comp = new NotificationComparator(mContext);
240        assertTrue(comp.isImportantPeople(mRecordStarredContact));
241        assertTrue(comp.isImportantPeople(mRecordContact));
242    }
243
244    private NotificationChannel getDefaultChannel() {
245        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
246                NotificationManager.IMPORTANCE_LOW);
247    }
248}
249