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.mockito.Matchers.anyInt;
19import static org.mockito.Matchers.anyString;
20import static org.mockito.Matchers.eq;
21import static org.mockito.Mockito.never;
22import static org.mockito.Mockito.times;
23import static org.mockito.Mockito.verify;
24
25import org.junit.Before;
26import org.junit.Test;
27import org.junit.runner.RunWith;
28import org.mockito.Mock;
29import org.mockito.Mockito;
30import org.mockito.MockitoAnnotations;
31
32import android.app.AlarmManager;
33import android.app.Notification;
34import android.app.NotificationChannel;
35import android.app.NotificationManager;
36import android.app.PendingIntent;
37import android.os.UserHandle;
38import android.service.notification.StatusBarNotification;
39import android.support.test.runner.AndroidJUnit4;
40import android.test.suitebuilder.annotation.SmallTest;
41
42import java.util.ArrayList;
43import java.util.List;
44
45@SmallTest
46@RunWith(AndroidJUnit4.class)
47public class GroupHelperTest extends NotificationTestCase {
48    private @Mock GroupHelper.Callback mCallback;
49
50    private GroupHelper mGroupHelper;
51
52    @Before
53    public void setUp() {
54        MockitoAnnotations.initMocks(this);
55
56        mGroupHelper = new GroupHelper(mCallback);
57    }
58
59    private StatusBarNotification getSbn(String pkg, int id, String tag,
60            UserHandle user, String groupKey) {
61        Notification.Builder nb = new Notification.Builder(getContext(), "test_channel_id")
62                .setContentTitle("A")
63                .setWhen(1205);
64        if (groupKey != null) {
65            nb.setGroup(groupKey);
66        }
67        return new StatusBarNotification(pkg, pkg, id, tag, 0, 0, nb.build(), user, null,
68                System.currentTimeMillis());
69    }
70
71    private StatusBarNotification getSbn(String pkg, int id, String tag,
72            UserHandle user) {
73        return getSbn(pkg, id, tag, user, null);
74    }
75
76    @Test
77    public void testNoGroup_postingUnderLimit() throws Exception {
78        final String pkg = "package";
79        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 1; i++) {
80            mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
81        }
82        verify(mCallback, never()).addAutoGroupSummary(
83                eq(UserHandle.USER_SYSTEM), eq(pkg), anyString());
84        verify(mCallback, never()).addAutoGroup(anyString());
85        verify(mCallback, never()).removeAutoGroup(anyString());
86        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
87    }
88
89    @Test
90    public void testNoGroup_multiPackage() throws Exception {
91        final String pkg = "package";
92        final String pkg2 = "package2";
93        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 1; i++) {
94            mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
95        }
96        mGroupHelper.onNotificationPosted(
97                getSbn(pkg2, GroupHelper.AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM));
98        verify(mCallback, never()).addAutoGroupSummary(
99                eq(UserHandle.USER_SYSTEM), eq(pkg), anyString());
100        verify(mCallback, never()).addAutoGroup(anyString());
101        verify(mCallback, never()).removeAutoGroup(anyString());
102        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
103    }
104
105    @Test
106    public void testNoGroup_multiUser() throws Exception {
107        final String pkg = "package";
108        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 1; i++) {
109            mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
110        }
111        mGroupHelper.onNotificationPosted(
112                getSbn(pkg, GroupHelper.AUTOGROUP_AT_COUNT, "four", UserHandle.ALL));
113        verify(mCallback, never()).addAutoGroupSummary(anyInt(), eq(pkg), anyString());
114        verify(mCallback, never()).addAutoGroup(anyString());
115        verify(mCallback, never()).removeAutoGroup(anyString());
116        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
117    }
118
119    @Test
120    public void testNoGroup_someAreGrouped() throws Exception {
121        final String pkg = "package";
122        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 1; i++) {
123            mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
124        }
125        mGroupHelper.onNotificationPosted(
126                getSbn(pkg, GroupHelper.AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM, "a"));
127        verify(mCallback, never()).addAutoGroupSummary(
128                eq(UserHandle.USER_SYSTEM), eq(pkg), anyString());
129        verify(mCallback, never()).addAutoGroup(anyString());
130        verify(mCallback, never()).removeAutoGroup(anyString());
131        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
132    }
133
134
135    @Test
136    public void testPostingOverLimit() throws Exception {
137        final String pkg = "package";
138        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT; i++) {
139            mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
140        }
141        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString());
142        verify(mCallback, times(GroupHelper.AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
143        verify(mCallback, never()).removeAutoGroup(anyString());
144        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
145    }
146
147    @Test
148    public void testDropToZeroRemoveGroup() throws Exception {
149        final String pkg = "package";
150        List<StatusBarNotification> posted = new ArrayList<>();
151        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT; i++) {
152            final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
153            posted.add(sbn);
154            mGroupHelper.onNotificationPosted(sbn);
155        }
156        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString());
157        verify(mCallback, times(GroupHelper.AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
158        verify(mCallback, never()).removeAutoGroup(anyString());
159        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
160        Mockito.reset(mCallback);
161
162        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 1; i++) {
163            mGroupHelper.onNotificationRemoved(posted.remove(0));
164        }
165        verify(mCallback, never()).removeAutoGroup(anyString());
166        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
167        Mockito.reset(mCallback);
168
169        mGroupHelper.onNotificationRemoved(posted.remove(0));
170        verify(mCallback, never()).removeAutoGroup(anyString());
171        verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString());
172    }
173
174    @Test
175    public void testAppStartsGrouping() throws Exception {
176        final String pkg = "package";
177        List<StatusBarNotification> posted = new ArrayList<>();
178        for (int i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT; i++) {
179            final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
180            posted.add(sbn);
181            mGroupHelper.onNotificationPosted(sbn);
182        }
183        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString());
184        verify(mCallback, times(GroupHelper.AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
185        verify(mCallback, never()).removeAutoGroup(anyString());
186        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
187        Mockito.reset(mCallback);
188
189        int i = 0;
190        for (i = 0; i < GroupHelper.AUTOGROUP_AT_COUNT - 2; i++) {
191            final StatusBarNotification sbn =
192                    getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group");
193            mGroupHelper.onNotificationPosted(sbn);
194        }
195        verify(mCallback, times(GroupHelper.AUTOGROUP_AT_COUNT - 2)).removeAutoGroup(anyString());
196        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
197        Mockito.reset(mCallback);
198
199        for (; i < GroupHelper.AUTOGROUP_AT_COUNT; i++) {
200            final StatusBarNotification sbn =
201                    getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group");
202            mGroupHelper.onNotificationPosted(sbn);
203        }
204        verify(mCallback, times(2)).removeAutoGroup(anyString());
205        verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString());
206    }
207}
208