1 /*
2  * Copyright (C) 2020 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 com.android.systemui.statusbar.notification.icon;
18 
19 import android.app.ActivityManager;
20 import android.app.Notification;
21 import android.app.NotificationChannel
22 import android.app.NotificationManager.IMPORTANCE_DEFAULT
23 import android.app.Person
24 import android.content.pm.LauncherApps
25 import android.content.pm.ShortcutInfo
26 import android.graphics.drawable.Drawable
27 import android.graphics.drawable.Icon
28 import android.os.SystemClock
29 import android.os.UserHandle
30 import android.testing.AndroidTestingRunner;
31 import androidx.test.InstrumentationRegistry
32 import androidx.test.filters.SmallTest
33 import com.android.systemui.SysuiTestCase
34 import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any
35 import com.android.systemui.statusbar.notification.collection.NotificationEntry
36 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
37 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
38 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
39 import org.junit.Assert.assertEquals
40 import org.junit.Before
41 import org.junit.Test
42 
43 import org.junit.runner.RunWith;
44 import org.mockito.Mock
45 import org.mockito.Mockito.`when`
46 import org.mockito.Mockito.anyInt
47 import org.mockito.MockitoAnnotations
48 
49 @SmallTest
50 @RunWith(AndroidTestingRunner::class)
51 class IconManagerTest: SysuiTestCase() {
52     companion object {
53         private const val TEST_PACKAGE_NAME = "test";
54         private const val TEST_UID = 0;
55     }
56 
57 
58     private var id = 0
59     private val context = InstrumentationRegistry.getTargetContext();
60     @Mock private lateinit var shortcut: ShortcutInfo
61     @Mock private lateinit var shortcutIc: Icon
62     @Mock private lateinit var messageIc: Icon
63     @Mock private lateinit var largeIc: Icon
64     @Mock private lateinit var smallIc: Icon
65     @Mock private lateinit var drawable: Drawable
66     @Mock private lateinit var row: ExpandableNotificationRow
67 
68     @Mock private lateinit var notifCollection: CommonNotifCollection
69     @Mock private lateinit var launcherApps: LauncherApps
70 
71     private val iconBuilder = IconBuilder(context)
72 
73     private lateinit var iconManager: IconManager
74 
75     @Before
76     fun setUp() {
77         MockitoAnnotations.initMocks(this)
78 
79         `when`(shortcutIc.loadDrawableAsUser(any(), anyInt())).thenReturn(drawable)
80         `when`(messageIc.loadDrawableAsUser(any(), anyInt())).thenReturn(drawable)
81         `when`(largeIc.loadDrawableAsUser(any(), anyInt())).thenReturn(drawable)
82         `when`(smallIc.loadDrawableAsUser(any(), anyInt())).thenReturn(drawable)
83 
84         `when`(shortcut.icon).thenReturn(shortcutIc)
85         `when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc)
86 
87         iconManager = IconManager(notifCollection, launcherApps, iconBuilder)
88     }
89 
90     @Test
91     fun testCreateIcons_importantConversation_shortcutIcon() {
92         val entry = notificationEntry(true, true, true)
93         entry?.channel?.isImportantConversation = true
94         entry?.let {
95             iconManager.createIcons(it)
96         }
97         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, shortcutIc)
98     }
99 
100     @Test
101     fun testCreateIcons_importantConversation_messageIcon() {
102         val entry = notificationEntry(false, true, true)
103         entry?.channel?.isImportantConversation = true
104         entry?.let {
105             iconManager.createIcons(it)
106         }
107         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, messageIc)
108     }
109 
110     @Test
111     fun testCreateIcons_importantConversation_largeIcon() {
112         val entry = notificationEntry(false, false, true)
113         entry?.channel?.isImportantConversation = true
114         entry?.let {
115             iconManager.createIcons(it)
116         }
117         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, largeIc)
118     }
119 
120     @Test
121     fun testCreateIcons_importantConversation_smallIcon() {
122         val entry = notificationEntry(false, false, false)
123         entry?.channel?.isImportantConversation = true
124         entry?.let {
125             iconManager.createIcons(it)
126         }
127         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, smallIc)
128     }
129 
130     @Test
131     fun testCreateIcons_notImportantConversation() {
132         val entry = notificationEntry(true, true, true)
133         entry?.let {
134             iconManager.createIcons(it)
135         }
136         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, smallIc)
137     }
138 
139     @Test
140     fun testCreateIcons_sensitiveImportantConversation() {
141         val entry = notificationEntry(true, false, false)
142         entry?.setSensitive(true, true);
143         entry?.channel?.isImportantConversation = true
144         entry?.let {
145             iconManager.createIcons(it)
146         }
147         assertEquals(entry?.icons?.statusBarIcon?.sourceIcon, shortcutIc)
148         assertEquals(entry?.icons?.shelfIcon?.sourceIcon, smallIc)
149         assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc)
150     }
151 
152     @Test
153     fun testUpdateIcons_sensitivityChange() {
154         val entry = notificationEntry(true, false, false)
155         entry?.channel?.isImportantConversation = true
156         entry?.setSensitive(true, true);
157         entry?.let {
158             iconManager.createIcons(it)
159         }
160         assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc)
161         entry?.setSensitive(false, false);
162         entry?.let {
163             iconManager.updateIcons(it)
164         }
165         assertEquals(entry?.icons?.shelfIcon?.sourceIcon, shortcutIc)
166     }
167 
168     private fun notificationEntry(
169             hasShortcut: Boolean,
170             hasMessage: Boolean,
171             hasLargeIcon: Boolean
172     ): NotificationEntry? {
173         val n = Notification.Builder(mContext, "id")
174                 .setSmallIcon(smallIc)
175                 .setContentTitle("Title")
176                 .setContentText("Text")
177 
178         if (hasMessage) {
179             n.style = Notification.MessagingStyle("")
180                     .addMessage(Notification.MessagingStyle.Message(
181                             "",
182                             SystemClock.currentThreadTimeMillis(),
183                             Person.Builder().setIcon(messageIc).build()
184                     ))
185         }
186 
187         if (hasLargeIcon) {
188             n.setLargeIcon(largeIc)
189         }
190 
191         val builder = NotificationEntryBuilder()
192                 .setPkg(TEST_PACKAGE_NAME)
193                 .setOpPkg(TEST_PACKAGE_NAME)
194                 .setUid(TEST_UID)
195                 .setId(id++)
196                 .setNotification(n.build())
197                 .setChannel(NotificationChannel("id", "", IMPORTANCE_DEFAULT))
198                 .setUser(UserHandle(ActivityManager.getCurrentUser()))
199 
200         if (hasShortcut) {
201             builder.setShortcutInfo(shortcut)
202         }
203 
204         val entry = builder.build()
205         entry.row = row
206         entry.setSensitive(false, true);
207         return entry
208     }
209 }
210