1/*
2 * Copyright (C) 2017 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 junit.framework.Assert.assertFalse;
19import static junit.framework.Assert.assertTrue;
20
21import static org.mockito.Mockito.mock;
22import static org.mockito.Mockito.when;
23
24import static android.app.NotificationManager.IMPORTANCE_HIGH;
25import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
26import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
27import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
28
29import android.app.ActivityManager;
30import android.app.Notification;
31import android.app.Notification.Builder;
32import android.app.NotificationChannel;
33import android.os.UserHandle;
34import android.service.notification.StatusBarNotification;
35import android.support.test.runner.AndroidJUnit4;
36import android.test.suitebuilder.annotation.SmallTest;
37
38import com.android.server.UiServiceTestCase;
39
40import org.junit.Before;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43import org.mockito.Mock;
44import org.mockito.MockitoAnnotations;
45
46@SmallTest
47@RunWith(AndroidJUnit4.class)
48public class BadgeExtractorTest extends UiServiceTestCase {
49
50    @Mock RankingConfig mConfig;
51
52    private String mPkg = "com.android.server.notification";
53    private int mId = 1001;
54    private String mTag = null;
55    private int mUid = 1000;
56    private int mPid = 2000;
57    private UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
58
59    @Before
60    public void setUp() {
61        MockitoAnnotations.initMocks(this);
62    }
63
64    private NotificationRecord getNotificationRecord(boolean showBadge, int importanceHigh) {
65        NotificationChannel channel = new NotificationChannel("a", "a", importanceHigh);
66        channel.setShowBadge(showBadge);
67        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
68
69        final Builder builder = new Builder(getContext())
70                .setContentTitle("foo")
71                .setSmallIcon(android.R.drawable.sym_def_app_icon)
72                .setPriority(Notification.PRIORITY_HIGH)
73                .setDefaults(Notification.DEFAULT_SOUND);
74
75        Notification n = builder.build();
76        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
77                mPid, n, mUser, null, System.currentTimeMillis());
78        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
79        return r;
80    }
81
82    //
83    // Tests
84    //
85
86    @Test
87    public void testAppYesChannelNo() throws Exception {
88        BadgeExtractor extractor = new BadgeExtractor();
89        extractor.setConfig(mConfig);
90
91        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
92        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
93        NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
94
95        extractor.process(r);
96
97        assertFalse(r.canShowBadge());
98    }
99
100    @Test
101    public void testAppNoChannelYes() throws Exception {
102        BadgeExtractor extractor = new BadgeExtractor();
103        extractor.setConfig(mConfig);
104
105        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
106        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
107        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
108
109        extractor.process(r);
110
111        assertFalse(r.canShowBadge());
112    }
113
114    @Test
115    public void testAppYesChannelYes() throws Exception {
116        BadgeExtractor extractor = new BadgeExtractor();
117        extractor.setConfig(mConfig);
118
119        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
120        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
121        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
122
123        extractor.process(r);
124
125        assertTrue(r.canShowBadge());
126    }
127
128    @Test
129    public void testAppNoChannelNo() throws Exception {
130        BadgeExtractor extractor = new BadgeExtractor();
131        extractor.setConfig(mConfig);
132
133        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
134        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
135        NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
136
137        extractor.process(r);
138
139        assertFalse(r.canShowBadge());
140    }
141
142    @Test
143    public void testAppYesChannelYesUserNo() throws Exception {
144        BadgeExtractor extractor = new BadgeExtractor();
145        extractor.setConfig(mConfig);
146
147        when(mConfig.badgingEnabled(mUser)).thenReturn(false);
148        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
149        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
150
151        extractor.process(r);
152
153        assertFalse(r.canShowBadge());
154    }
155
156    @Test
157    public void testDndOverridesYes() {
158        BadgeExtractor extractor = new BadgeExtractor();
159        extractor.setConfig(mConfig);
160
161        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
162        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
163        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
164        r.setIntercepted(true);
165        r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
166
167        extractor.process(r);
168
169        assertFalse(r.canShowBadge());
170    }
171
172    @Test
173    public void testDndOConsidersInterception() {
174        BadgeExtractor extractor = new BadgeExtractor();
175        extractor.setConfig(mConfig);
176
177        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
178        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
179        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
180        r.setIntercepted(false);
181        r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
182
183        extractor.process(r);
184
185        assertTrue(r.canShowBadge());
186    }
187
188    @Test
189    public void testDndConsidersSuppressedVisualEffects() {
190        BadgeExtractor extractor = new BadgeExtractor();
191        extractor.setConfig(mConfig);
192
193        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
194        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
195        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
196        r.setIntercepted(true);
197        r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
198
199        extractor.process(r);
200
201        assertTrue(r.canShowBadge());
202    }
203}
204