1 /* 2 * Copyright (C) 2019 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.app; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.app.NotificationHistory.HistoricalNotification; 22 import android.graphics.drawable.Icon; 23 import android.os.Parcel; 24 import android.platform.test.annotations.Presubmit; 25 26 import androidx.test.InstrumentationRegistry; 27 import androidx.test.ext.junit.runners.AndroidJUnit4; 28 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.HashSet; 35 import java.util.List; 36 import java.util.Set; 37 38 @RunWith(AndroidJUnit4.class) 39 @Presubmit 40 public class NotificationHistoryTest { 41 getHistoricalNotification(int index)42 private static HistoricalNotification getHistoricalNotification(int index) { 43 return getHistoricalNotification("package" + index, index); 44 } 45 getHistoricalNotification(String packageName, int index)46 private static HistoricalNotification getHistoricalNotification(String packageName, int index) { 47 return getHistoricalNotification(packageName, index, /* includeIcon= */ true); 48 } 49 getHistoricalNotification(String packageName, int index, boolean includeIcon)50 private static HistoricalNotification getHistoricalNotification(String packageName, int index, 51 boolean includeIcon) { 52 String expectedChannelName = "channelName" + index; 53 String expectedChannelId = "channelId" + index; 54 int expectedUid = 1123456 + index; 55 int expectedUserId = 11 + index; 56 long expectedPostTime = 987654321 + index; 57 String expectedTitle = "title" + index; 58 String expectedText = "text" + index; 59 Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(), 60 index); 61 String conversationId = null; 62 if (index % 2 == 0) { 63 conversationId = "convo" + index; 64 } 65 66 return new HistoricalNotification.Builder() 67 .setPackage(packageName) 68 .setChannelName(expectedChannelName) 69 .setChannelId(expectedChannelId) 70 .setUid(expectedUid) 71 .setUserId(expectedUserId) 72 .setPostedTimeMs(expectedPostTime) 73 .setTitle(expectedTitle) 74 .setText(expectedText) 75 .setIcon(includeIcon ? expectedIcon : null) 76 .setConversationId(conversationId) 77 .build(); 78 } 79 80 @Test testHistoricalNotificationBuilder()81 public void testHistoricalNotificationBuilder() { 82 String expectedPackage = "package"; 83 String expectedChannelName = "channelName"; 84 String expectedChannelId = "channelId"; 85 int expectedUid = 1123456; 86 int expectedUserId = 11; 87 long expectedPostTime = 987654321; 88 String expectedTitle = "title"; 89 String expectedText = "text"; 90 Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(), 91 android.R.drawable.btn_star); 92 String expectedConversationId = "convo"; 93 94 HistoricalNotification n = new HistoricalNotification.Builder() 95 .setPackage(expectedPackage) 96 .setChannelName(expectedChannelName) 97 .setChannelId(expectedChannelId) 98 .setUid(expectedUid) 99 .setUserId(expectedUserId) 100 .setPostedTimeMs(expectedPostTime) 101 .setTitle(expectedTitle) 102 .setText(expectedText) 103 .setIcon(expectedIcon) 104 .setConversationId(expectedConversationId) 105 .build(); 106 107 assertThat(n.getPackage()).isEqualTo(expectedPackage); 108 assertThat(n.getChannelName()).isEqualTo(expectedChannelName); 109 assertThat(n.getChannelId()).isEqualTo(expectedChannelId); 110 assertThat(n.getUid()).isEqualTo(expectedUid); 111 assertThat(n.getUserId()).isEqualTo(expectedUserId); 112 assertThat(n.getPostedTimeMs()).isEqualTo(expectedPostTime); 113 assertThat(n.getTitle()).isEqualTo(expectedTitle); 114 assertThat(n.getText()).isEqualTo(expectedText); 115 assertThat(expectedIcon.sameAs(n.getIcon())).isTrue(); 116 assertThat(n.getConversationId()).isEqualTo(expectedConversationId); 117 } 118 119 @Test testAddNotificationToWrite()120 public void testAddNotificationToWrite() { 121 NotificationHistory history = new NotificationHistory(); 122 HistoricalNotification n = getHistoricalNotification(0); 123 HistoricalNotification n2 = getHistoricalNotification(1); 124 125 history.addNotificationToWrite(n2); 126 history.addNotificationToWrite(n); 127 128 assertThat(history.getNotificationsToWrite().size()).isEqualTo(2); 129 assertThat(history.getNotificationsToWrite().get(0)).isSameInstanceAs(n2); 130 assertThat(history.getNotificationsToWrite().get(1)).isSameInstanceAs(n); 131 assertThat(history.getHistoryCount()).isEqualTo(2); 132 } 133 134 @Test testAddNotificationsToWrite()135 public void testAddNotificationsToWrite() { 136 NotificationHistory history = new NotificationHistory(); 137 HistoricalNotification n = getHistoricalNotification(3); 138 HistoricalNotification n2 = getHistoricalNotification(1); 139 HistoricalNotification n5 = getHistoricalNotification(0); 140 history.addNotificationToWrite(n2); 141 history.addNotificationToWrite(n); 142 history.addNotificationToWrite(n5); 143 144 NotificationHistory secondHistory = new NotificationHistory(); 145 HistoricalNotification n3 = getHistoricalNotification(4); 146 HistoricalNotification n4 = getHistoricalNotification(2); 147 secondHistory.addNotificationToWrite(n4); 148 secondHistory.addNotificationToWrite(n3); 149 150 history.addNotificationsToWrite(secondHistory); 151 152 assertThat(history.getNotificationsToWrite().size()).isEqualTo(5); 153 assertThat(history.getNotificationsToWrite().get(0)).isSameInstanceAs(n3); 154 assertThat(history.getNotificationsToWrite().get(1)).isSameInstanceAs(n); 155 assertThat(history.getNotificationsToWrite().get(2)).isSameInstanceAs(n4); 156 assertThat(history.getNotificationsToWrite().get(3)).isSameInstanceAs(n2); 157 assertThat(history.getNotificationsToWrite().get(4)).isSameInstanceAs(n5); 158 assertThat(history.getHistoryCount()).isEqualTo(5); 159 160 assertThat(history.getPooledStringsToWrite()).asList().contains(n2.getChannelName()); 161 assertThat(history.getPooledStringsToWrite()).asList().contains(n4.getPackage()); 162 } 163 164 @Test testPoolStringsFromNotifications()165 public void testPoolStringsFromNotifications() { 166 NotificationHistory history = new NotificationHistory(); 167 168 List<String> expectedStrings = new ArrayList<>(); 169 for (int i = 1; i <= 10; i++) { 170 HistoricalNotification n = getHistoricalNotification(i); 171 expectedStrings.add(n.getPackage()); 172 expectedStrings.add(n.getChannelName()); 173 expectedStrings.add(n.getChannelId()); 174 if (n.getConversationId() != null) { 175 expectedStrings.add(n.getConversationId()); 176 } 177 history.addNotificationToWrite(n); 178 } 179 180 history.poolStringsFromNotifications(); 181 182 assertThat(history.getPooledStringsToWrite().length).isEqualTo(expectedStrings.size()); 183 String previous = null; 184 for (String actual : history.getPooledStringsToWrite()) { 185 assertThat(expectedStrings).contains(actual); 186 187 if (previous != null) { 188 assertThat(actual).isGreaterThan(previous); 189 } 190 previous = actual; 191 } 192 } 193 194 @Test testAddPooledStrings()195 public void testAddPooledStrings() { 196 NotificationHistory history = new NotificationHistory(); 197 198 List<String> expectedStrings = new ArrayList<>(); 199 for (int i = 1; i <= 10; i++) { 200 HistoricalNotification n = getHistoricalNotification(i); 201 expectedStrings.add(n.getPackage()); 202 expectedStrings.add(n.getChannelName()); 203 expectedStrings.add(n.getChannelId()); 204 if (n.getConversationId() != null) { 205 expectedStrings.add(n.getConversationId()); 206 } 207 history.addNotificationToWrite(n); 208 } 209 210 history.addPooledStrings(expectedStrings); 211 212 String[] actualStrings = history.getPooledStringsToWrite(); 213 assertThat(actualStrings.length).isEqualTo(expectedStrings.size()); 214 String previous = null; 215 for (String actual : actualStrings) { 216 assertThat(expectedStrings).contains(actual); 217 218 if (previous != null) { 219 assertThat(actual).isGreaterThan(previous); 220 } 221 previous = actual; 222 } 223 } 224 225 @Test testRemoveNotificationsFromWrite()226 public void testRemoveNotificationsFromWrite() { 227 NotificationHistory history = new NotificationHistory(); 228 229 List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>(); 230 List<String> postRemoveExpectedStrings = new ArrayList<>(); 231 for (int i = 1; i <= 10; i++) { 232 HistoricalNotification n = 233 getHistoricalNotification((i % 2 == 0) ? "pkgEven" : "pkgOdd", i); 234 235 if (i % 2 == 0) { 236 postRemoveExpectedStrings.add(n.getPackage()); 237 postRemoveExpectedStrings.add(n.getChannelName()); 238 postRemoveExpectedStrings.add(n.getChannelId()); 239 if (n.getConversationId() != null) { 240 postRemoveExpectedStrings.add(n.getConversationId()); 241 } 242 postRemoveExpectedEntries.add(n); 243 } 244 245 history.addNotificationToWrite(n); 246 } 247 248 history.poolStringsFromNotifications(); 249 250 assertThat(history.getNotificationsToWrite().size()).isEqualTo(10); 251 // 2 package names and 10 * 2 unique channel names and ids and 5 conversation ids 252 assertThat(history.getPooledStringsToWrite().length).isEqualTo(27); 253 254 history.removeNotificationsFromWrite("pkgOdd"); 255 256 257 // 1 package names and 5 * 2 unique channel names and ids and 5 conversation ids 258 assertThat(history.getPooledStringsToWrite().length).isEqualTo(16); 259 assertThat(history.getNotificationsToWrite()) 260 .containsExactlyElementsIn(postRemoveExpectedEntries); 261 } 262 263 @Test testRemoveNotificationFromWrite()264 public void testRemoveNotificationFromWrite() { 265 NotificationHistory history = new NotificationHistory(); 266 267 List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>(); 268 List<String> postRemoveExpectedStrings = new ArrayList<>(); 269 for (int i = 1; i <= 10; i++) { 270 HistoricalNotification n = getHistoricalNotification("pkg", i); 271 272 if (987654323 != n.getPostedTimeMs()) { 273 postRemoveExpectedStrings.add(n.getPackage()); 274 postRemoveExpectedStrings.add(n.getChannelName()); 275 postRemoveExpectedStrings.add(n.getChannelId()); 276 if (n.getConversationId() != null) { 277 postRemoveExpectedStrings.add(n.getConversationId()); 278 } 279 postRemoveExpectedEntries.add(n); 280 } 281 282 history.addNotificationToWrite(n); 283 } 284 285 history.poolStringsFromNotifications(); 286 287 assertThat(history.getNotificationsToWrite().size()).isEqualTo(10); 288 // 1 package name and 20 unique channel names and ids and 5 conversation ids 289 assertThat(history.getPooledStringsToWrite().length).isEqualTo(26); 290 291 history.removeNotificationFromWrite("pkg", 987654323); 292 293 294 // 1 package names and 9 * 2 unique channel names and ids and 4 conversation ids 295 assertThat(history.getPooledStringsToWrite().length).isEqualTo(23); 296 assertThat(history.getNotificationsToWrite()) 297 .containsExactlyElementsIn(postRemoveExpectedEntries); 298 } 299 300 @Test testRemoveConversationNotificationFromWrite()301 public void testRemoveConversationNotificationFromWrite() { 302 NotificationHistory history = new NotificationHistory(); 303 304 List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>(); 305 List<String> postRemoveExpectedStrings = new ArrayList<>(); 306 for (int i = 1; i <= 10; i++) { 307 HistoricalNotification n = getHistoricalNotification("pkg", i); 308 309 if (i != 2 && i != 4) { 310 postRemoveExpectedStrings.add(n.getPackage()); 311 postRemoveExpectedStrings.add(n.getChannelName()); 312 postRemoveExpectedStrings.add(n.getChannelId()); 313 if (n.getConversationId() != null) { 314 postRemoveExpectedStrings.add(n.getConversationId()); 315 } 316 postRemoveExpectedEntries.add(n); 317 } 318 319 history.addNotificationToWrite(n); 320 } 321 // add second notification with the same conversation id that will be removed 322 history.addNotificationToWrite(getHistoricalNotification("pkg", 2)); 323 324 history.poolStringsFromNotifications(); 325 326 assertThat(history.getNotificationsToWrite().size()).isEqualTo(11); 327 // 1 package name and 20 unique channel names and ids and 5 conversation ids 328 assertThat(history.getPooledStringsToWrite().length).isEqualTo(26); 329 330 history.removeConversationsFromWrite("pkg", Set.of("convo2", "convo4")); 331 332 // 1 package names and 8 * 2 unique channel names and ids and 3 conversation ids 333 assertThat(history.getPooledStringsToWrite().length).isEqualTo(20); 334 assertThat(history.getNotificationsToWrite()) 335 .containsExactlyElementsIn(postRemoveExpectedEntries); 336 } 337 338 @Test testRemoveChannelFromWrite()339 public void testRemoveChannelFromWrite() { 340 NotificationHistory history = new NotificationHistory(); 341 342 List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>(); 343 Set<String> postRemoveExpectedStrings = new HashSet<>(); 344 for (int i = 1; i <= 10; i++) { 345 HistoricalNotification n = getHistoricalNotification("pkg", i); 346 347 // Remove channel numbers 5 and 6 348 if (i != 5 && i != 6) { 349 postRemoveExpectedStrings.add(n.getPackage()); 350 postRemoveExpectedStrings.add(n.getChannelName()); 351 postRemoveExpectedStrings.add(n.getChannelId()); 352 if (n.getConversationId() != null) { 353 postRemoveExpectedStrings.add(n.getConversationId()); 354 } 355 postRemoveExpectedEntries.add(n); 356 } 357 358 history.addNotificationToWrite(n); 359 } 360 // add second notification with the same channel id that will also be removed 361 history.addNotificationToWrite(getHistoricalNotification("pkg", 6)); 362 363 history.poolStringsFromNotifications(); 364 365 assertThat(history.getNotificationsToWrite().size()).isEqualTo(11); 366 // 1 package name and 20 unique channel names and ids and 5 conversation ids 367 assertThat(history.getPooledStringsToWrite().length).isEqualTo(26); 368 369 history.removeChannelFromWrite("pkg", "channelId5"); 370 history.removeChannelFromWrite("pkg", "channelId6"); 371 372 // 1 package names and 8 * 2 unique channel names and ids and 4 conversation ids 373 assertThat(history.getPooledStringsToWrite().length).isEqualTo(21); 374 assertThat(Arrays.asList(history.getPooledStringsToWrite())) 375 .containsExactlyElementsIn(postRemoveExpectedStrings); 376 assertThat(history.getNotificationsToWrite()) 377 .containsExactlyElementsIn(postRemoveExpectedEntries); 378 } 379 380 @Test testParceling()381 public void testParceling() { 382 NotificationHistory history = new NotificationHistory(); 383 384 List<HistoricalNotification> expectedEntries = new ArrayList<>(); 385 for (int i = 10; i >= 1; i--) { 386 HistoricalNotification n = getHistoricalNotification("packageName" + i, 387 i, /* includeIcon= */ false); 388 expectedEntries.add(n); 389 history.addNotificationToWrite(n); 390 } 391 history.poolStringsFromNotifications(); 392 393 Parcel parcel = Parcel.obtain(); 394 history.writeToParcel(parcel, 0); 395 parcel.setDataPosition(0); 396 NotificationHistory parceledHistory = NotificationHistory.CREATOR.createFromParcel(parcel); 397 398 assertThat(parceledHistory.getHistoryCount()).isEqualTo(expectedEntries.size()); 399 400 for (int i = 0; i < expectedEntries.size(); i++) { 401 assertThat(parceledHistory.hasNextNotification()).isTrue(); 402 403 HistoricalNotification postParcelNotification = parceledHistory.getNextNotification(); 404 assertThat(postParcelNotification).isEqualTo(expectedEntries.get(i)); 405 } 406 assertThat(parceledHistory.hasNextNotification()).isFalse(); 407 assertThat(parceledHistory.getNextNotification()).isNull(); 408 } 409 } 410