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.pm; 17 18import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith; 19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; 20 21import android.content.ComponentName; 22import android.content.pm.ShortcutInfo; 23import android.test.suitebuilder.annotation.SmallTest; 24 25import com.android.frameworks.servicestests.R; 26import com.android.server.pm.ShortcutService.ConfigConstants; 27 28/** 29 * Tests related to shortcut rank auto-adjustment. 30 */ 31@SmallTest 32public class ShortcutManagerTest3 extends BaseShortcutManagerTest { 33 34 private static final String CALLING_PACKAGE = CALLING_PACKAGE_1; 35 36 private static final ComponentName A1 = new ComponentName(CALLING_PACKAGE, 37 ShortcutActivity.class.getName()); 38 39 private static final ComponentName A2 = new ComponentName(CALLING_PACKAGE, 40 ShortcutActivity2.class.getName()); 41 42 private static final ComponentName A3 = new ComponentName(CALLING_PACKAGE, 43 ShortcutActivity3.class.getName()); 44 45 private ShortcutInfo shortcut(String id, ComponentName activity, int rank) { 46 return makeShortcutWithActivityAndRank(id, activity, rank); 47 } 48 49 private ShortcutInfo shortcut(String id, ComponentName activity) { 50 return makeShortcutWithActivityAndRank(id, activity, ShortcutInfo.RANK_NOT_SET); 51 } 52 53 @Override 54 protected void setUp() throws Exception { 55 super.setUp(); 56 57 // We don't need throttling during this test class, and also relax the max cap. 58 mService.updateConfigurationLocked( 59 ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999," 60 + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999" 61 ); 62 63 setCaller(CALLING_PACKAGE, USER_0); 64 } 65 66 private void publishManifestShortcuts(ComponentName activity, int resId) { 67 addManifestShortcutResource(activity, resId); 68 updatePackageVersion(CALLING_PACKAGE, 1); 69 mService.mPackageMonitor.onReceive(getTestContext(), 70 genPackageAddIntent(CALLING_PACKAGE, USER_0)); 71 } 72 73 public void testSetDynamicShortcuts_noManifestShortcuts() { 74 mManager.setDynamicShortcuts(list( 75 shortcut("s1", A1) 76 )); 77 78 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 79 .haveRanksInOrder("s1"); 80 81 assertTrue(mManager.setDynamicShortcuts(list( 82 shortcut("s5", A1), 83 shortcut("s4", A1), 84 shortcut("s3", A1) 85 ))); 86 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 87 .haveRanksInOrder("s5", "s4", "s3"); 88 89 // RANK_NOT_SET is always the last. 90 assertTrue(mManager.setDynamicShortcuts(list( 91 shortcut("s5", A1), 92 shortcut("s4", A1, 5), 93 shortcut("s3", A1, 3), 94 shortcut("s2", A1) 95 ))); 96 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 97 .haveRanksInOrder("s3", "s4", "s5", "s2"); 98 99 // Same rank, preserve the argument order. 100 assertTrue(mManager.setDynamicShortcuts(list( 101 shortcut("s5", A1, 5), 102 shortcut("s4", A1, 0), 103 shortcut("s3", A1, 5) 104 ))); 105 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 106 .haveRanksInOrder("s4", "s5", "s3"); 107 108 // Multiple activities. 109 assertTrue(mManager.setDynamicShortcuts(list( 110 shortcut("s5", A1), 111 shortcut("s4", A2), 112 shortcut("s3", A3) 113 ))); 114 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 115 .haveRanksInOrder("s5"); 116 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 117 .haveRanksInOrder("s4"); 118 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3) 119 .haveRanksInOrder("s3"); 120 121 assertTrue(mManager.setDynamicShortcuts(list( 122 shortcut("s5", A1, 5), 123 shortcut("s4", A1), 124 shortcut("s3", A1, 5), 125 shortcut("x5", A2, 5), 126 shortcut("x4", A2), 127 shortcut("x3", A2, 1) 128 ))); 129 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 130 .haveRanksInOrder("s5", "s3", "s4"); 131 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 132 .haveRanksInOrder("x3", "x5", "x4"); 133 134 // Clear. Make sure it wouldn't lead to invalid internals state. 135 // (ShortcutService.verifyStates() will do so internally.) 136 assertTrue(mManager.setDynamicShortcuts(list())); 137 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1).isEmpty(); 138 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2).isEmpty(); 139 } 140 141 private void runTestWithManifestShortcuts(Runnable r) { 142 publishManifestShortcuts(A1, R.xml.shortcut_5_alt); 143 publishManifestShortcuts(A2, R.xml.shortcut_1); 144 145 assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1) 146 .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt"); 147 148 assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2) 149 .haveRanksInOrder("ms1"); 150 151 // Existence of manifest shortcuts shouldn't affect dynamic shortcut ranks, 152 // so running another test here should pass. 153 r.run(); 154 155 // And dynamic shortcut tests shouldn't affect manifest shortcuts, so repeat the 156 // same check. 157 assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1) 158 .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt"); 159 160 assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2) 161 .haveRanksInOrder("ms1"); 162 } 163 164 public void testSetDynamicShortcuts_withManifestShortcuts() { 165 runTestWithManifestShortcuts(() -> testSetDynamicShortcuts_noManifestShortcuts()); 166 } 167 168 public void testAddDynamicShortcuts_noManifestShortcuts() { 169 mManager.addDynamicShortcuts(list( 170 shortcut("s1", A1) 171 )); 172 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 173 .haveRanksInOrder("s1"); 174 175 //------------------------------------------------------ 176 long lastApiTime = ++mInjectedCurrentTimeMillis; 177 178 mManager.addDynamicShortcuts(list( 179 shortcut("s5", A1, 0), 180 shortcut("s4", A1), 181 shortcut("s2", A1, 3), 182 shortcut("x1", A2), 183 shortcut("x3", A2, 2), 184 shortcut("x2", A2, 2), 185 shortcut("s3", A1, 0) 186 )); 187 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 188 .haveRanksInOrder("s5", "s3", "s1", "s2", "s4"); 189 190 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 191 .haveRanksInOrder("x3", "x2", "x1"); 192 193 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 194 .haveIds("s5", "s3", "s1", "s2", "s4", "x3", "x2", "x1"); 195 196 //------------------------------------------------------ 197 lastApiTime = ++mInjectedCurrentTimeMillis; 198 199 mManager.addDynamicShortcuts(list( 200 shortcut("s1", A1, 1) 201 )); 202 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 203 .haveRanksInOrder("s5", "s1", "s3", "s2", "s4"); 204 205 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 206 .haveRanksInOrder("x3", "x2", "x1"); 207 208 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 209 .haveIds("s1", "s3"); 210 211 //------------------------------------------------------ 212 lastApiTime = ++mInjectedCurrentTimeMillis; 213 214 mManager.addDynamicShortcuts(list( 215 shortcut("s1", A1, 1), 216 217 // This is add, not update, so the following means s5 will have NO_RANK, 218 // which puts it at the end. 219 shortcut("s5", A1), 220 shortcut("s3", A1, 0), 221 222 // s10 also has NO_RANK, so it'll be put at the end, even after "s5" as we preserve 223 // the argument order. 224 shortcut("s10", A1), 225 226 // Note we're changing the activity for x2. 227 shortcut("x2", A1, 0), 228 shortcut("x10", A2) 229 )); 230 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 231 .haveRanksInOrder("s3", "x2", "s1", "s2", "s4", "s5", "s10"); 232 233 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 234 .haveRanksInOrder("x3", "x1", "x10"); 235 236 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 237 .haveIds("s3", "x2", "s1", "s5", "s10", "x1", "x10"); 238 239 //------------------------------------------------------ 240 lastApiTime = ++mInjectedCurrentTimeMillis; 241 242 // Change the activities again. 243 mManager.addDynamicShortcuts(list( 244 shortcut("s1", A2), 245 shortcut("s2", A2, 999) 246 )); 247 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 248 .haveRanksInOrder("s3", "x2", "s4", "s5", "s10"); 249 250 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 251 .haveRanksInOrder("x3", "x1", "x10", "s2", "s1"); 252 253 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 254 .haveIds("s1", "s2", "s4", "s5", "s10"); 255 } 256 257 public void testAddDynamicShortcuts_withManifestShortcuts() { 258 runTestWithManifestShortcuts(() -> testAddDynamicShortcuts_noManifestShortcuts()); 259 } 260 261 public void testUpdateShortcuts_noManifestShortcuts() { 262 mManager.addDynamicShortcuts(list( 263 shortcut("s5", A1, 0), 264 shortcut("s4", A1), 265 shortcut("s2", A1, 3), 266 shortcut("x1", A2), 267 shortcut("x3", A2, 2), 268 shortcut("x2", A2, 2), 269 shortcut("s3", A1, 0) 270 )); 271 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 272 .haveRanksInOrder("s5", "s3", "s2", "s4"); 273 274 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 275 .haveRanksInOrder("x3", "x2", "x1"); 276 277 //------------------------------------------------------ 278 long lastApiTime = ++mInjectedCurrentTimeMillis; 279 280 mManager.updateShortcuts(list()); 281 // Same order. 282 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 283 .haveRanksInOrder("s5", "s3", "s2", "s4"); 284 285 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 286 .haveRanksInOrder("x3", "x2", "x1"); 287 288 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 289 .isEmpty(); 290 291 292 runWithCaller(LAUNCHER_1, USER_0, () -> { 293 mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0); 294 }); 295 // Still same order. 296 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 297 .haveRanksInOrder("s5", "s3", "s2", "s4"); 298 299 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 300 .haveRanksInOrder("x3", "x2", "x1"); 301 302 //------------------------------------------------------ 303 lastApiTime = ++mInjectedCurrentTimeMillis; 304 305 mManager.updateShortcuts(list( 306 shortcut("s4", A1, 1), 307 308 // Rank not changing, should keep the same positions. 309 // c.f. in case of addDynamicShortcuts, this means "put them at the end". 310 shortcut("s3", A1), 311 shortcut("x2", A2) 312 )); 313 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 314 .haveRanksInOrder("s5", "s4", "s3", "s2"); 315 316 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 317 .haveRanksInOrder("x3", "x2", "x1"); 318 319 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 320 .haveIds("s4", "s3", "s2", "x2"); 321 322 //------------------------------------------------------ 323 lastApiTime = ++mInjectedCurrentTimeMillis; 324 325 mManager.updateShortcuts(list( 326 shortcut("s4", A1, 0), 327 328 // Change the activity without specifying a rank -> keep the same rank. 329 shortcut("s5", A2), 330 331 // Change the activity without specifying a rank -> assign a new rank. 332 shortcut("x2", A1, 2), 333 334 // "xx" doesn't exist, so it'll be ignored. 335 shortcut("xx", A1, 0) 336 )); 337 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 338 .haveRanksInOrder("s4", "x2", "s3", "s2"); 339 340 // Interesting case: both x3 and s5 originally had rank=0, and in this case s5 has moved 341 // to A2 without changing the rank. So they're tie for the new rank, as well as 342 // the "rank changed" bit. Also in this case, "s5" won't have an implicit order, since 343 // its rank isn't changing. So we sort them by ID, thus s5 comes before x3. 344 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 345 .haveRanksInOrder("s5", "x3", "x1"); 346 347 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 348 .haveIds("s4", "x2", "s5", "x3"); 349 350 //------------------------------------------------------ 351 lastApiTime = ++mInjectedCurrentTimeMillis; 352 353 mManager.updateShortcuts(list( 354 shortcut("s3", A3))); 355 356 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 357 .haveRanksInOrder("s4", "x2", "s2"); 358 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 359 .haveRanksInOrder("s5", "x3", "x1"); 360 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3) 361 .haveRanksInOrder("s3"); 362 363 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 364 .haveIds("s3", "s2"); 365 } 366 367 public void testUpdateShortcuts_withManifestShortcuts() { 368 runTestWithManifestShortcuts(() -> testUpdateShortcuts_noManifestShortcuts()); 369 } 370 371 public void testDeleteDynamicShortcuts_noManifestShortcuts() { 372 mManager.addDynamicShortcuts(list( 373 shortcut("s5", A1, 0), 374 shortcut("s4", A1), 375 shortcut("s2", A1, 3), 376 shortcut("x1", A2), 377 shortcut("x3", A2, 2), 378 shortcut("x2", A2, 2), 379 shortcut("s3", A1, 0) 380 )); 381 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 382 .haveRanksInOrder("s5", "s3", "s2", "s4"); 383 384 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 385 .haveRanksInOrder("x3", "x2", "x1"); 386 387 //------------------------------------------------------ 388 long lastApiTime = ++mInjectedCurrentTimeMillis; 389 390 mManager.removeDynamicShortcuts(list()); 391 392 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 393 .haveRanksInOrder("s5", "s3", "s2", "s4"); 394 395 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 396 .haveRanksInOrder("x3", "x2", "x1"); 397 398 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 399 .isEmpty(); 400 401 runWithCaller(LAUNCHER_1, USER_0, () -> { 402 mLauncherApps.pinShortcuts( 403 CALLING_PACKAGE, list("s2", "s4", "x1", "x2"), HANDLE_USER_0); 404 }); 405 // Still same order. 406 407 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 408 .haveRanksInOrder("s5", "s3", "s2", "s4"); 409 410 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 411 .haveRanksInOrder("x3", "x2", "x1"); 412 413 //------------------------------------------------------ 414 lastApiTime = ++mInjectedCurrentTimeMillis; 415 416 mManager.removeDynamicShortcuts(list("s3", "x1", "xxxx")); 417 418 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 419 .haveRanksInOrder("s5", "s2", "s4"); 420 421 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 422 .haveRanksInOrder("x3", "x2"); 423 424 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 425 .haveIds("s2", "s4"); 426 } 427 428 public void testDeleteDynamicShortcuts_withManifestShortcuts() { 429 runTestWithManifestShortcuts(() -> testDeleteDynamicShortcuts_noManifestShortcuts()); 430 } 431 432 public void testDisableShortcuts_noManifestShortcuts() { 433 mManager.addDynamicShortcuts(list( 434 shortcut("s5", A1, 0), 435 shortcut("s4", A1), 436 shortcut("s2", A1, 3), 437 shortcut("x1", A2), 438 shortcut("x3", A2, 2), 439 shortcut("x2", A2, 2), 440 shortcut("s3", A1, 0) 441 )); 442 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 443 .haveRanksInOrder("s5", "s3", "s2", "s4"); 444 445 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 446 .haveRanksInOrder("x3", "x2", "x1"); 447 448 //------------------------------------------------------ 449 long lastApiTime = ++mInjectedCurrentTimeMillis; 450 451 mManager.disableShortcuts(list()); 452 453 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 454 .haveRanksInOrder("s5", "s3", "s2", "s4"); 455 456 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 457 .haveRanksInOrder("x3", "x2", "x1"); 458 459 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 460 .isEmpty(); 461 462 //------------------------------------------------------ 463 lastApiTime = ++mInjectedCurrentTimeMillis; 464 465 mManager.disableShortcuts(list("s3", "x1", "xxxx")); 466 467 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 468 .haveRanksInOrder("s5", "s2", "s4"); 469 470 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 471 .haveRanksInOrder("x3", "x2"); 472 473 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 474 .haveIds("s2", "s4"); 475 476 runWithCaller(LAUNCHER_1, USER_0, () -> { 477 mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0); 478 }); 479 // Still same order. 480 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 481 .haveRanksInOrder("s5", "s2", "s4"); 482 483 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 484 .haveRanksInOrder("x3", "x2"); 485 486 //------------------------------------------------------ 487 lastApiTime = ++mInjectedCurrentTimeMillis; 488 489 mManager.disableShortcuts(list("s2", "x3")); 490 491 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) 492 .haveRanksInOrder("s5", "s4"); 493 494 assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) 495 .haveRanksInOrder("x2"); 496 497 assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) 498 .haveIds("s4", "x2"); 499 } 500 501 public void testDisableShortcuts_withManifestShortcuts() { 502 runTestWithManifestShortcuts(() -> testDisableShortcuts_noManifestShortcuts()); 503 } 504 505} 506