ShortcutManagerTest2.java revision 76269928e677725e2d9b28e2e3aa79961a60a1d0
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.assertBundlesEqual; 19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException; 20import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith; 21import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; 22import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle; 23import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.parceled; 24import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set; 25 26import static org.mockito.Matchers.anyInt; 27import static org.mockito.Matchers.anyString; 28import static org.mockito.Matchers.eq; 29import static org.mockito.Mockito.reset; 30import static org.mockito.Mockito.times; 31import static org.mockito.Mockito.verify; 32 33import android.Manifest.permission; 34import android.app.ActivityManager; 35import android.content.ComponentName; 36import android.content.Intent; 37import android.content.pm.ShortcutInfo; 38import android.content.res.Resources; 39import android.graphics.BitmapFactory; 40import android.graphics.drawable.Icon; 41import android.net.Uri; 42import android.os.PersistableBundle; 43import android.os.UserHandle; 44import android.test.MoreAsserts; 45import android.test.suitebuilder.annotation.SmallTest; 46 47import com.android.frameworks.servicestests.R; 48import com.android.server.pm.ShortcutService.ConfigConstants; 49 50import java.io.File; 51import java.io.IOException; 52import java.io.PrintWriter; 53import java.io.StringWriter; 54import java.util.Locale; 55 56/** 57 * Tests for ShortcutService and ShortcutManager. 58 * 59 m FrameworksServicesTests && 60 adb install \ 61 -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && 62 adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \ 63 -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner 64 */ 65@SmallTest 66public class ShortcutManagerTest2 extends BaseShortcutManagerTest { 67 // ShortcutInfo tests 68 69 public void testShortcutInfoMissingMandatoryFields() { 70 // Disable throttling. 71 mService.updateConfigurationLocked( 72 ShortcutService.ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999," 73 + ShortcutService.ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999" 74 ); 75 76 assertExpectException( 77 IllegalArgumentException.class, 78 "ID must be provided", 79 () -> new ShortcutInfo.Builder(getTestContext()).build()); 80 81 assertExpectException( 82 RuntimeException.class, 83 "id cannot be empty", 84 () -> new ShortcutInfo.Builder(getTestContext(), null)); 85 86 assertExpectException( 87 RuntimeException.class, 88 "id cannot be empty", 89 () -> new ShortcutInfo.Builder(getTestContext(), "")); 90 91 assertExpectException( 92 RuntimeException.class, 93 "intent cannot be null", 94 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null)); 95 96 assertExpectException( 97 RuntimeException.class, 98 "action must be set", 99 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent())); 100 101 assertExpectException( 102 RuntimeException.class, 103 "activity cannot be null", 104 () -> new ShortcutInfo.Builder(getTestContext(), "id").setActivity(null)); 105 106 assertExpectException( 107 RuntimeException.class, 108 "shortLabel cannot be empty", 109 () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(null)); 110 111 assertExpectException( 112 RuntimeException.class, 113 "shortLabel cannot be empty", 114 () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel("")); 115 116 assertExpectException( 117 RuntimeException.class, 118 "longLabel cannot be empty", 119 () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(null)); 120 121 assertExpectException( 122 RuntimeException.class, 123 "longLabel cannot be empty", 124 () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel("")); 125 126 assertExpectException( 127 RuntimeException.class, 128 "disabledMessage cannot be empty", 129 () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(null)); 130 131 assertExpectException( 132 RuntimeException.class, 133 "disabledMessage cannot be empty", 134 () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage("")); 135 136 assertExpectException(NullPointerException.class, "action must be set", 137 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent())); 138 139 assertExpectException( 140 IllegalArgumentException.class, "Short label must be provided", () -> { 141 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 142 .setActivity(new ComponentName(getTestContext().getPackageName(), "s")) 143 .build(); 144 assertTrue(getManager().setDynamicShortcuts(list(si))); 145 }); 146 147 // same for add. 148 assertExpectException( 149 IllegalArgumentException.class, "Short label must be provided", () -> { 150 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 151 .setActivity(new ComponentName(getTestContext().getPackageName(), "s")) 152 .build(); 153 assertTrue(getManager().addDynamicShortcuts(list(si))); 154 }); 155 156 assertExpectException(NullPointerException.class, "Intent must be provided", () -> { 157 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 158 .setActivity(new ComponentName(getTestContext().getPackageName(), "s")) 159 .setShortLabel("x") 160 .build(); 161 assertTrue(getManager().setDynamicShortcuts(list(si))); 162 }); 163 164 // same for add. 165 assertExpectException(NullPointerException.class, "Intent must be provided", () -> { 166 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 167 .setActivity(new ComponentName(getTestContext().getPackageName(), "s")) 168 .setShortLabel("x") 169 .build(); 170 assertTrue(getManager().addDynamicShortcuts(list(si))); 171 }); 172 173 assertExpectException( 174 IllegalStateException.class, "does not belong to package", () -> { 175 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 176 .setActivity(new ComponentName("xxx", "s")) 177 .build(); 178 assertTrue(getManager().setDynamicShortcuts(list(si))); 179 }); 180 181 // same for add. 182 assertExpectException( 183 IllegalStateException.class, "does not belong to package", () -> { 184 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 185 .setActivity(new ComponentName("xxx", "s")) 186 .build(); 187 assertTrue(getManager().addDynamicShortcuts(list(si))); 188 }); 189 190 // Now all activities are not main. 191 mMainActivityChecker = (component, userId) -> false; 192 193 assertExpectException( 194 IllegalStateException.class, "is not main", () -> { 195 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 196 .setActivity(new ComponentName(getTestContext(), "s")) 197 .build(); 198 assertTrue(getManager().setDynamicShortcuts(list(si))); 199 }); 200 // For add 201 assertExpectException( 202 IllegalStateException.class, "is not main", () -> { 203 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 204 .setActivity(new ComponentName(getTestContext(), "s")) 205 .build(); 206 assertTrue(getManager().addDynamicShortcuts(list(si))); 207 }); 208 // For update 209 assertExpectException( 210 IllegalStateException.class, "is not main", () -> { 211 ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") 212 .setActivity(new ComponentName(getTestContext(), "s")) 213 .build(); 214 assertTrue(getManager().updateShortcuts(list(si))); 215 }); 216 } 217 218 public void testShortcutInfoParcel() { 219 setCaller(CALLING_PACKAGE_1, USER_10); 220 ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext) 221 .setId("id") 222 .setTitle("title") 223 .setIntent(makeIntent("action", ShortcutActivity.class)) 224 .build()); 225 assertEquals(mClientContext.getPackageName(), si.getPackage()); 226 assertEquals(USER_10, si.getUserId()); 227 assertEquals(HANDLE_USER_10, si.getUserHandle()); 228 assertEquals("id", si.getId()); 229 assertEquals("title", si.getTitle()); 230 assertEquals("action", si.getIntent().getAction()); 231 232 PersistableBundle pb = new PersistableBundle(); 233 pb.putInt("k", 1); 234 235 si = new ShortcutInfo.Builder(getTestContext()) 236 .setId("id") 237 .setActivity(new ComponentName("a", "b")) 238 .setIcon(Icon.createWithResource(mClientContext, 123)) 239 .setTitle("title") 240 .setText("text") 241 .setDisabledMessage("dismes") 242 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 243 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 244 .setRank(123) 245 .setExtras(pb) 246 .build(); 247 si.addFlags(ShortcutInfo.FLAG_PINNED); 248 si.setBitmapPath("abc"); 249 si.setIconResourceId(456); 250 251 si = parceled(si); 252 253 assertEquals(getTestContext().getPackageName(), si.getPackage()); 254 assertEquals("id", si.getId()); 255 assertEquals(new ComponentName("a", "b"), si.getActivity()); 256 assertEquals(123, si.getIcon().getResId()); 257 assertEquals("title", si.getTitle()); 258 assertEquals("text", si.getText()); 259 assertEquals("dismes", si.getDisabledMessage()); 260 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 261 assertEquals("action", si.getIntent().getAction()); 262 assertEquals("val", si.getIntent().getStringExtra("key")); 263 assertEquals(123, si.getRank()); 264 assertEquals(1, si.getExtras().getInt("k")); 265 266 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 267 assertEquals("abc", si.getBitmapPath()); 268 assertEquals(456, si.getIconResourceId()); 269 270 assertEquals(0, si.getTitleResId()); 271 assertEquals(null, si.getTitleResName()); 272 assertEquals(0, si.getTextResId()); 273 assertEquals(null, si.getTextResName()); 274 assertEquals(0, si.getDisabledMessageResourceId()); 275 assertEquals(null, si.getDisabledMessageResName()); 276 } 277 278 public void testShortcutInfoParcel_resId() { 279 setCaller(CALLING_PACKAGE_1, USER_10); 280 ShortcutInfo si; 281 282 PersistableBundle pb = new PersistableBundle(); 283 pb.putInt("k", 1); 284 285 si = new ShortcutInfo.Builder(getTestContext()) 286 .setId("id") 287 .setActivity(new ComponentName("a", "b")) 288 .setIcon(Icon.createWithResource(mClientContext, 123)) 289 .setTitleResId(10) 290 .setTextResId(11) 291 .setDisabledMessageResId(12) 292 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 293 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 294 .setRank(123) 295 .setExtras(pb) 296 .build(); 297 si.addFlags(ShortcutInfo.FLAG_PINNED); 298 si.setBitmapPath("abc"); 299 si.setIconResourceId(456); 300 301 lookupAndFillInResourceNames(si); 302 303 si = parceled(si); 304 305 assertEquals(getTestContext().getPackageName(), si.getPackage()); 306 assertEquals("id", si.getId()); 307 assertEquals(new ComponentName("a", "b"), si.getActivity()); 308 assertEquals(123, si.getIcon().getResId()); 309 assertEquals(10, si.getTitleResId()); 310 assertEquals("r10", si.getTitleResName()); 311 assertEquals(11, si.getTextResId()); 312 assertEquals("r11", si.getTextResName()); 313 assertEquals(12, si.getDisabledMessageResourceId()); 314 assertEquals("r12", si.getDisabledMessageResName()); 315 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 316 assertEquals("action", si.getIntent().getAction()); 317 assertEquals("val", si.getIntent().getStringExtra("key")); 318 assertEquals(123, si.getRank()); 319 assertEquals(1, si.getExtras().getInt("k")); 320 321 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 322 assertEquals("abc", si.getBitmapPath()); 323 assertEquals(456, si.getIconResourceId()); 324 assertEquals("string/r456", si.getIconResName()); 325 } 326 327 public void testShortcutInfoClone() { 328 setCaller(CALLING_PACKAGE_1, USER_11); 329 330 PersistableBundle pb = new PersistableBundle(); 331 pb.putInt("k", 1); 332 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 333 .setId("id") 334 .setActivity(new ComponentName("a", "b")) 335 .setIcon(Icon.createWithResource(mClientContext, 123)) 336 .setTitle("title") 337 .setText("text") 338 .setDisabledMessage("dismes") 339 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 340 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 341 .setRank(123) 342 .setExtras(pb) 343 .build(); 344 sorig.addFlags(ShortcutInfo.FLAG_PINNED); 345 sorig.setBitmapPath("abc"); 346 sorig.setIconResourceId(456); 347 348 lookupAndFillInResourceNames(sorig); 349 350 ShortcutInfo si = sorig.clone(/* clone flags*/ 0); 351 352 assertEquals(USER_11, si.getUserId()); 353 assertEquals(HANDLE_USER_11, si.getUserHandle()); 354 assertEquals(mClientContext.getPackageName(), si.getPackage()); 355 assertEquals("id", si.getId()); 356 assertEquals(new ComponentName("a", "b"), si.getActivity()); 357 assertEquals(123, si.getIcon().getResId()); 358 assertEquals("title", si.getTitle()); 359 assertEquals("text", si.getText()); 360 assertEquals("dismes", si.getDisabledMessage()); 361 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 362 assertEquals("action", si.getIntent().getAction()); 363 assertEquals("val", si.getIntent().getStringExtra("key")); 364 assertEquals(123, si.getRank()); 365 assertEquals(1, si.getExtras().getInt("k")); 366 367 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 368 assertEquals("abc", si.getBitmapPath()); 369 assertEquals(456, si.getIconResourceId()); 370 assertEquals("string/r456", si.getIconResName()); 371 372 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR); 373 374 assertEquals(mClientContext.getPackageName(), si.getPackage()); 375 assertEquals("id", si.getId()); 376 assertEquals(new ComponentName("a", "b"), si.getActivity()); 377 assertEquals(null, si.getIcon()); 378 assertEquals("title", si.getTitle()); 379 assertEquals("text", si.getText()); 380 assertEquals("dismes", si.getDisabledMessage()); 381 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 382 assertEquals("action", si.getIntent().getAction()); 383 assertEquals("val", si.getIntent().getStringExtra("key")); 384 assertEquals(123, si.getRank()); 385 assertEquals(1, si.getExtras().getInt("k")); 386 387 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 388 assertEquals(null, si.getBitmapPath()); 389 390 assertEquals(456, si.getIconResourceId()); 391 assertEquals(null, si.getIconResName()); 392 393 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); 394 395 assertEquals(mClientContext.getPackageName(), si.getPackage()); 396 assertEquals("id", si.getId()); 397 assertEquals(new ComponentName("a", "b"), si.getActivity()); 398 assertEquals(null, si.getIcon()); 399 assertEquals("title", si.getTitle()); 400 assertEquals("text", si.getText()); 401 assertEquals("dismes", si.getDisabledMessage()); 402 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 403 assertEquals(null, si.getIntent()); 404 assertEquals(123, si.getRank()); 405 assertEquals(1, si.getExtras().getInt("k")); 406 407 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 408 assertEquals(null, si.getBitmapPath()); 409 410 assertEquals(456, si.getIconResourceId()); 411 assertEquals(null, si.getIconResName()); 412 413 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO); 414 415 assertEquals(mClientContext.getPackageName(), si.getPackage()); 416 assertEquals("id", si.getId()); 417 assertEquals(new ComponentName("a", "b"), si.getActivity()); 418 assertEquals(null, si.getIcon()); 419 assertEquals(null, si.getTitle()); 420 assertEquals(null, si.getText()); 421 assertEquals(null, si.getDisabledMessage()); 422 assertEquals(null, si.getCategories()); 423 assertEquals(null, si.getIntent()); 424 assertEquals(0, si.getRank()); 425 assertEquals(null, si.getExtras()); 426 427 assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags()); 428 assertEquals(null, si.getBitmapPath()); 429 430 assertEquals(456, si.getIconResourceId()); 431 assertEquals(null, si.getIconResName()); 432 } 433 434 public void testShortcutInfoClone_resId() { 435 setCaller(CALLING_PACKAGE_1, USER_11); 436 437 PersistableBundle pb = new PersistableBundle(); 438 pb.putInt("k", 1); 439 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 440 .setId("id") 441 .setActivity(new ComponentName("a", "b")) 442 .setIcon(Icon.createWithResource(mClientContext, 123)) 443 .setTitleResId(10) 444 .setTextResId(11) 445 .setDisabledMessageResId(12) 446 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 447 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 448 .setRank(123) 449 .setExtras(pb) 450 .build(); 451 sorig.addFlags(ShortcutInfo.FLAG_PINNED); 452 sorig.setBitmapPath("abc"); 453 sorig.setIconResourceId(456); 454 455 lookupAndFillInResourceNames(sorig); 456 457 ShortcutInfo si = sorig.clone(/* clone flags*/ 0); 458 459 assertEquals(USER_11, si.getUserId()); 460 assertEquals(HANDLE_USER_11, si.getUserHandle()); 461 assertEquals(mClientContext.getPackageName(), si.getPackage()); 462 assertEquals("id", si.getId()); 463 assertEquals(new ComponentName("a", "b"), si.getActivity()); 464 assertEquals(123, si.getIcon().getResId()); 465 assertEquals(10, si.getTitleResId()); 466 assertEquals("r10", si.getTitleResName()); 467 assertEquals(11, si.getTextResId()); 468 assertEquals("r11", si.getTextResName()); 469 assertEquals(12, si.getDisabledMessageResourceId()); 470 assertEquals("r12", si.getDisabledMessageResName()); 471 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 472 assertEquals("action", si.getIntent().getAction()); 473 assertEquals("val", si.getIntent().getStringExtra("key")); 474 assertEquals(123, si.getRank()); 475 assertEquals(1, si.getExtras().getInt("k")); 476 477 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 478 assertEquals("abc", si.getBitmapPath()); 479 assertEquals(456, si.getIconResourceId()); 480 assertEquals("string/r456", si.getIconResName()); 481 482 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR); 483 484 assertEquals(mClientContext.getPackageName(), si.getPackage()); 485 assertEquals("id", si.getId()); 486 assertEquals(new ComponentName("a", "b"), si.getActivity()); 487 assertEquals(null, si.getIcon()); 488 assertEquals(10, si.getTitleResId()); 489 assertEquals(null, si.getTitleResName()); 490 assertEquals(11, si.getTextResId()); 491 assertEquals(null, si.getTextResName()); 492 assertEquals(12, si.getDisabledMessageResourceId()); 493 assertEquals(null, si.getDisabledMessageResName()); 494 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 495 assertEquals("action", si.getIntent().getAction()); 496 assertEquals("val", si.getIntent().getStringExtra("key")); 497 assertEquals(123, si.getRank()); 498 assertEquals(1, si.getExtras().getInt("k")); 499 500 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 501 assertEquals(null, si.getBitmapPath()); 502 503 assertEquals(456, si.getIconResourceId()); 504 assertEquals(null, si.getIconResName()); 505 506 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); 507 508 assertEquals(mClientContext.getPackageName(), si.getPackage()); 509 assertEquals("id", si.getId()); 510 assertEquals(new ComponentName("a", "b"), si.getActivity()); 511 assertEquals(null, si.getIcon()); 512 assertEquals(10, si.getTitleResId()); 513 assertEquals(null, si.getTitleResName()); 514 assertEquals(11, si.getTextResId()); 515 assertEquals(null, si.getTextResName()); 516 assertEquals(12, si.getDisabledMessageResourceId()); 517 assertEquals(null, si.getDisabledMessageResName()); 518 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 519 assertEquals(null, si.getIntent()); 520 assertEquals(123, si.getRank()); 521 assertEquals(1, si.getExtras().getInt("k")); 522 523 assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); 524 assertEquals(null, si.getBitmapPath()); 525 526 assertEquals(456, si.getIconResourceId()); 527 assertEquals(null, si.getIconResName()); 528 529 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO); 530 531 assertEquals(mClientContext.getPackageName(), si.getPackage()); 532 assertEquals("id", si.getId()); 533 assertEquals(new ComponentName("a", "b"), si.getActivity()); 534 assertEquals(null, si.getIcon()); 535 assertEquals(0, si.getTitleResId()); 536 assertEquals(null, si.getTitleResName()); 537 assertEquals(0, si.getTextResId()); 538 assertEquals(null, si.getTextResName()); 539 assertEquals(0, si.getDisabledMessageResourceId()); 540 assertEquals(null, si.getDisabledMessageResName()); 541 assertEquals(null, si.getCategories()); 542 assertEquals(null, si.getIntent()); 543 assertEquals(0, si.getRank()); 544 assertEquals(null, si.getExtras()); 545 546 assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags()); 547 assertEquals(null, si.getBitmapPath()); 548 549 assertEquals(456, si.getIconResourceId()); 550 assertEquals(null, si.getIconResName()); 551 } 552 553 public void testShortcutInfoClone_minimum() { 554 PersistableBundle pb = new PersistableBundle(); 555 pb.putInt("k", 1); 556 ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext()) 557 .setId("id") 558 .setTitle("title") 559 .setIntent(makeIntent("action", ShortcutActivity.class)) 560 .build(); 561 ShortcutInfo si = sorig.clone(/* clone flags*/ 0); 562 563 assertEquals(getTestContext().getPackageName(), si.getPackage()); 564 assertEquals("id", si.getId()); 565 assertEquals("title", si.getTitle()); 566 assertEquals("action", si.getIntent().getAction()); 567 assertEquals(null, si.getCategories()); 568 569 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR); 570 571 assertEquals(getTestContext().getPackageName(), si.getPackage()); 572 assertEquals("id", si.getId()); 573 assertEquals("title", si.getTitle()); 574 assertEquals("action", si.getIntent().getAction()); 575 assertEquals(null, si.getCategories()); 576 577 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); 578 579 assertEquals(getTestContext().getPackageName(), si.getPackage()); 580 assertEquals("id", si.getId()); 581 assertEquals("title", si.getTitle()); 582 assertEquals(null, si.getIntent()); 583 assertEquals(null, si.getCategories()); 584 585 si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO); 586 587 assertEquals(getTestContext().getPackageName(), si.getPackage()); 588 assertEquals("id", si.getId()); 589 assertEquals(null, si.getTitle()); 590 assertEquals(null, si.getIntent()); 591 assertEquals(null, si.getCategories()); 592 } 593 594 public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException { 595 PersistableBundle pb = new PersistableBundle(); 596 pb.putInt("k", 1); 597 ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext()) 598 .setId("id") 599 .setActivity(new ComponentName("a", "b")) 600 .setIcon(Icon.createWithResource(mClientContext, 123)) 601 .setTitle("title") 602 .setText("text") 603 .setDisabledMessage("dismes") 604 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 605 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 606 .setRank(123) 607 .setExtras(pb) 608 .build(); 609 sorig.addFlags(ShortcutInfo.FLAG_PINNED); 610 sorig.setBitmapPath("abc"); 611 sorig.setIconResourceId(456); 612 613 lookupAndFillInResourceNames(sorig); 614 615 ShortcutInfo si; 616 617 si = sorig.clone(/* flags=*/ 0); 618 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 619 .setActivity(new ComponentName("x", "y")).build()); 620 assertEquals("text", si.getText()); 621 assertEquals(123, si.getRank()); 622 assertEquals(new ComponentName("x", "y"), si.getActivity()); 623 624 si = sorig.clone(/* flags=*/ 0); 625 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 626 .setIcon(Icon.createWithResource(mClientContext, 456)).build()); 627 assertEquals("text", si.getText()); 628 assertEquals(456, si.getIcon().getResId()); 629 assertEquals(0, si.getIconResourceId()); 630 assertEquals(null, si.getIconResName()); 631 assertEquals(null, si.getBitmapPath()); 632 633 si = sorig.clone(/* flags=*/ 0); 634 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 635 .setTitle("xyz").build()); 636 assertEquals("text", si.getText()); 637 assertEquals("xyz", si.getTitle()); 638 assertEquals(0, si.getTitleResId()); 639 640 si = sorig.clone(/* flags=*/ 0); 641 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 642 .setTitleResId(123).build()); 643 assertEquals("text", si.getText()); 644 assertEquals(null, si.getTitle()); 645 assertEquals(123, si.getTitleResId()); 646 647 si = sorig.clone(/* flags=*/ 0); 648 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 649 .setText("xxx").build()); 650 assertEquals(123, si.getRank()); 651 assertEquals("xxx", si.getText()); 652 assertEquals(0, si.getTextResId()); 653 654 si = sorig.clone(/* flags=*/ 0); 655 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 656 .setTextResId(1111).build()); 657 assertEquals(123, si.getRank()); 658 assertEquals(null, si.getText()); 659 assertEquals(1111, si.getTextResId()); 660 661 si = sorig.clone(/* flags=*/ 0); 662 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 663 .setDisabledMessage("xxx").build()); 664 assertEquals(123, si.getRank()); 665 assertEquals("xxx", si.getDisabledMessage()); 666 assertEquals(0, si.getDisabledMessageResourceId()); 667 668 si = sorig.clone(/* flags=*/ 0); 669 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 670 .setDisabledMessageResId(11111).build()); 671 assertEquals(123, si.getRank()); 672 assertEquals(null, si.getDisabledMessage()); 673 assertEquals(11111, si.getDisabledMessageResourceId()); 674 675 si = sorig.clone(/* flags=*/ 0); 676 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 677 .setCategories(set()).build()); 678 assertEquals("text", si.getText()); 679 assertEquals(set(), si.getCategories()); 680 681 si = sorig.clone(/* flags=*/ 0); 682 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 683 .setCategories(set("x")).build()); 684 assertEquals("text", si.getText()); 685 assertEquals(set("x"), si.getCategories()); 686 687 si = sorig.clone(/* flags=*/ 0); 688 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 689 .setIntent(makeIntent("action2", ShortcutActivity.class)).build()); 690 assertEquals("text", si.getText()); 691 assertEquals("action2", si.getIntent().getAction()); 692 assertEquals(null, si.getIntent().getStringExtra("key")); 693 694 si = sorig.clone(/* flags=*/ 0); 695 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 696 .setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build()); 697 assertEquals("text", si.getText()); 698 assertEquals("action3", si.getIntent().getAction()); 699 assertEquals("x", si.getIntent().getStringExtra("key")); 700 701 si = sorig.clone(/* flags=*/ 0); 702 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 703 .setRank(999).build()); 704 assertEquals("text", si.getText()); 705 assertEquals(999, si.getRank()); 706 707 708 PersistableBundle pb2 = new PersistableBundle(); 709 pb2.putInt("x", 99); 710 711 si = sorig.clone(/* flags=*/ 0); 712 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 713 .setExtras(pb2).build()); 714 assertEquals("text", si.getText()); 715 assertEquals(99, si.getExtras().getInt("x")); 716 } 717 718 public void testShortcutInfoCopyNonNullFieldsFrom_resId() throws InterruptedException { 719 PersistableBundle pb = new PersistableBundle(); 720 pb.putInt("k", 1); 721 ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext()) 722 .setId("id") 723 .setActivity(new ComponentName("a", "b")) 724 .setIcon(Icon.createWithResource(mClientContext, 123)) 725 .setTitleResId(10) 726 .setTextResId(11) 727 .setDisabledMessageResId(12) 728 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 729 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 730 .setRank(123) 731 .setExtras(pb) 732 .build(); 733 sorig.addFlags(ShortcutInfo.FLAG_PINNED); 734 sorig.setBitmapPath("abc"); 735 sorig.setIconResourceId(456); 736 737 ShortcutInfo si; 738 739 si = sorig.clone(/* flags=*/ 0); 740 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 741 .setActivity(new ComponentName("x", "y")).build()); 742 assertEquals(11, si.getTextResId()); 743 assertEquals(new ComponentName("x", "y"), si.getActivity()); 744 745 si = sorig.clone(/* flags=*/ 0); 746 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 747 .setIcon(Icon.createWithResource(mClientContext, 456)).build()); 748 assertEquals(11, si.getTextResId()); 749 assertEquals(456, si.getIcon().getResId()); 750 assertEquals(0, si.getIconResourceId()); 751 assertEquals(null, si.getIconResName()); 752 assertEquals(null, si.getBitmapPath()); 753 754 si = sorig.clone(/* flags=*/ 0); 755 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 756 .setTitle("xyz").build()); 757 assertEquals(11, si.getTextResId()); 758 assertEquals("xyz", si.getTitle()); 759 assertEquals(0, si.getTitleResId()); 760 assertEquals(null, si.getTitleResName()); 761 762 si = sorig.clone(/* flags=*/ 0); 763 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 764 .setTitleResId(123).build()); 765 assertEquals(11, si.getTextResId()); 766 assertEquals(null, si.getTitle()); 767 assertEquals(123, si.getTitleResId()); 768 assertEquals(null, si.getTitleResName()); 769 770 si = sorig.clone(/* flags=*/ 0); 771 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 772 .setText("xxx").build()); 773 assertEquals(123, si.getRank()); 774 assertEquals("xxx", si.getText()); 775 assertEquals(0, si.getTextResId()); 776 assertEquals(null, si.getTextResName()); 777 778 si = sorig.clone(/* flags=*/ 0); 779 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 780 .setTextResId(1111).build()); 781 assertEquals(123, si.getRank()); 782 assertEquals(null, si.getText()); 783 assertEquals(1111, si.getTextResId()); 784 assertEquals(null, si.getTextResName()); 785 786 si = sorig.clone(/* flags=*/ 0); 787 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 788 .setDisabledMessage("xxx").build()); 789 assertEquals(123, si.getRank()); 790 assertEquals("xxx", si.getDisabledMessage()); 791 assertEquals(0, si.getDisabledMessageResourceId()); 792 assertEquals(null, si.getDisabledMessageResName()); 793 794 si = sorig.clone(/* flags=*/ 0); 795 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 796 .setDisabledMessageResId(11111).build()); 797 assertEquals(123, si.getRank()); 798 assertEquals(null, si.getDisabledMessage()); 799 assertEquals(11111, si.getDisabledMessageResourceId()); 800 assertEquals(null, si.getDisabledMessageResName()); 801 802 si = sorig.clone(/* flags=*/ 0); 803 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 804 .setCategories(set()).build()); 805 assertEquals(11, si.getTextResId()); 806 assertEquals(set(), si.getCategories()); 807 808 si = sorig.clone(/* flags=*/ 0); 809 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 810 .setCategories(set("x")).build()); 811 assertEquals(11, si.getTextResId()); 812 assertEquals(set("x"), si.getCategories()); 813 814 si = sorig.clone(/* flags=*/ 0); 815 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 816 .setIntent(makeIntent("action2", ShortcutActivity.class)).build()); 817 assertEquals(11, si.getTextResId()); 818 assertEquals("action2", si.getIntent().getAction()); 819 assertEquals(null, si.getIntent().getStringExtra("key")); 820 821 si = sorig.clone(/* flags=*/ 0); 822 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 823 .setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build()); 824 assertEquals(11, si.getTextResId()); 825 assertEquals("action3", si.getIntent().getAction()); 826 assertEquals("x", si.getIntent().getStringExtra("key")); 827 828 si = sorig.clone(/* flags=*/ 0); 829 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 830 .setRank(999).build()); 831 assertEquals(11, si.getTextResId()); 832 assertEquals(999, si.getRank()); 833 834 835 PersistableBundle pb2 = new PersistableBundle(); 836 pb2.putInt("x", 99); 837 838 si = sorig.clone(/* flags=*/ 0); 839 si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") 840 .setExtras(pb2).build()); 841 assertEquals(11, si.getTextResId()); 842 assertEquals(99, si.getExtras().getInt("x")); 843 } 844 845 public void testShortcutInfoSaveAndLoad() throws InterruptedException { 846 setCaller(CALLING_PACKAGE_1, USER_10); 847 848 final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( 849 getTestContext().getResources(), R.drawable.black_32x32)); 850 851 PersistableBundle pb = new PersistableBundle(); 852 pb.putInt("k", 1); 853 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 854 .setId("id") 855 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 856 .setIcon(bmp32x32) 857 .setTitle("title") 858 .setText("text") 859 .setDisabledMessage("dismes") 860 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 861 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 862 .setRank(123) 863 .setExtras(pb) 864 .build(); 865 sorig.setTimestamp(mInjectedCurrentTimeMillis); 866 867 ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext) 868 .setId("id2") 869 .setTitle("x") 870 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 871 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 872 .setRank(456) 873 .build(); 874 sorig2.setTimestamp(mInjectedCurrentTimeMillis); 875 876 mManager.addDynamicShortcuts(list(sorig, sorig2)); 877 878 mInjectedCurrentTimeMillis += 1; 879 final long now = mInjectedCurrentTimeMillis; 880 mInjectedCurrentTimeMillis += 1; 881 882 // Save and load. 883 mService.saveDirtyInfo(); 884 initService(); 885 mService.handleUnlockUser(USER_10); 886 887 ShortcutInfo si; 888 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10); 889 890 assertEquals(USER_10, si.getUserId()); 891 assertEquals(HANDLE_USER_10, si.getUserHandle()); 892 assertEquals(CALLING_PACKAGE_1, si.getPackage()); 893 assertEquals("id", si.getId()); 894 assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); 895 assertEquals(null, si.getIcon()); 896 assertEquals("title", si.getTitle()); 897 assertEquals("text", si.getText()); 898 assertEquals("dismes", si.getDisabledMessage()); 899 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 900 assertEquals("action", si.getIntent().getAction()); 901 assertEquals("val", si.getIntent().getStringExtra("key")); 902 assertEquals(0, si.getRank()); 903 assertEquals(1, si.getExtras().getInt("k")); 904 905 assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE 906 | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags()); 907 assertNotNull(si.getBitmapPath()); // Something should be set. 908 assertEquals(0, si.getIconResourceId()); 909 assertTrue(si.getLastChangedTimestamp() < now); 910 911 // Make sure ranks are saved too. Because of the auto-adjusting, we need two shortcuts 912 // to test it. 913 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10); 914 assertEquals(1, si.getRank()); 915 } 916 917 public void testShortcutInfoSaveAndLoad_resId() throws InterruptedException { 918 setCaller(CALLING_PACKAGE_1, USER_10); 919 920 final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32); 921 922 PersistableBundle pb = new PersistableBundle(); 923 pb.putInt("k", 1); 924 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 925 .setId("id") 926 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 927 .setIcon(res32x32) 928 .setTitleResId(10) 929 .setTextResId(11) 930 .setDisabledMessageResId(12) 931 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 932 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 933 .setRank(123) 934 .setExtras(pb) 935 .build(); 936 sorig.setTimestamp(mInjectedCurrentTimeMillis); 937 938 ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext) 939 .setId("id2") 940 .setTitle("x") 941 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 942 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 943 .setRank(456) 944 .build(); 945 sorig2.setTimestamp(mInjectedCurrentTimeMillis); 946 947 mManager.addDynamicShortcuts(list(sorig, sorig2)); 948 949 mInjectedCurrentTimeMillis += 1; 950 final long now = mInjectedCurrentTimeMillis; 951 mInjectedCurrentTimeMillis += 1; 952 953 // Save and load. 954 mService.saveDirtyInfo(); 955 initService(); 956 mService.handleUnlockUser(USER_10); 957 958 ShortcutInfo si; 959 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10); 960 961 assertEquals(USER_10, si.getUserId()); 962 assertEquals(HANDLE_USER_10, si.getUserHandle()); 963 assertEquals(CALLING_PACKAGE_1, si.getPackage()); 964 assertEquals("id", si.getId()); 965 assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); 966 assertEquals(null, si.getIcon()); 967 assertEquals(10, si.getTitleResId()); 968 assertEquals("r10", si.getTitleResName()); 969 assertEquals(11, si.getTextResId()); 970 assertEquals("r11", si.getTextResName()); 971 assertEquals(12, si.getDisabledMessageResourceId()); 972 assertEquals("r12", si.getDisabledMessageResName()); 973 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 974 assertEquals("action", si.getIntent().getAction()); 975 assertEquals("val", si.getIntent().getStringExtra("key")); 976 assertEquals(0, si.getRank()); 977 assertEquals(1, si.getExtras().getInt("k")); 978 979 assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_RES 980 | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags()); 981 assertNull(si.getBitmapPath()); 982 assertEquals(R.drawable.black_32x32, si.getIconResourceId()); 983 assertTrue(si.getLastChangedTimestamp() < now); 984 985 // Make sure ranks are saved too. Because of the auto-adjusting, we need two shortcuts 986 // to test it. 987 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10); 988 assertEquals(1, si.getRank()); 989 } 990 991 public void testShortcutInfoSaveAndLoad_forBackup() { 992 setCaller(CALLING_PACKAGE_1, USER_0); 993 994 final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( 995 getTestContext().getResources(), R.drawable.black_32x32)); 996 997 PersistableBundle pb = new PersistableBundle(); 998 pb.putInt("k", 1); 999 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 1000 .setId("id") 1001 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 1002 .setIcon(bmp32x32) 1003 .setTitle("title") 1004 .setText("text") 1005 .setDisabledMessage("dismes") 1006 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 1007 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 1008 .setRank(123) 1009 .setExtras(pb) 1010 .build(); 1011 1012 ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext) 1013 .setId("id2") 1014 .setTitle("x") 1015 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 1016 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 1017 .setRank(456) 1018 .build(); 1019 1020 mManager.addDynamicShortcuts(list(sorig, sorig2)); 1021 1022 // Dynamic shortcuts won't be backed up, so we need to pin it. 1023 setCaller(LAUNCHER_1, USER_0); 1024 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0); 1025 1026 // Do backup & restore. 1027 backupAndRestore(); 1028 1029 mService.handleUnlockUser(USER_0); // Load user-0. 1030 1031 ShortcutInfo si; 1032 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0); 1033 1034 assertEquals(CALLING_PACKAGE_1, si.getPackage()); 1035 assertEquals("id", si.getId()); 1036 assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); 1037 assertEquals(null, si.getIcon()); 1038 assertEquals("title", si.getTitle()); 1039 assertEquals("text", si.getText()); 1040 assertEquals("dismes", si.getDisabledMessage()); 1041 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 1042 assertEquals("action", si.getIntent().getAction()); 1043 assertEquals("val", si.getIntent().getStringExtra("key")); 1044 assertEquals(0, si.getRank()); 1045 assertEquals(1, si.getExtras().getInt("k")); 1046 1047 assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags()); 1048 assertNull(si.getBitmapPath()); // No icon. 1049 assertEquals(0, si.getIconResourceId()); 1050 1051 // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank. 1052 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0); 1053 assertEquals(0, si.getRank()); 1054 } 1055 1056 public void testShortcutInfoSaveAndLoad_forBackup_resId() { 1057 setCaller(CALLING_PACKAGE_1, USER_0); 1058 1059 final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32); 1060 1061 PersistableBundle pb = new PersistableBundle(); 1062 pb.putInt("k", 1); 1063 ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext) 1064 .setId("id") 1065 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 1066 .setIcon(res32x32) 1067 .setTitleResId(10) 1068 .setTextResId(11) 1069 .setDisabledMessageResId(12) 1070 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) 1071 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 1072 .setRank(123) 1073 .setExtras(pb) 1074 .build(); 1075 1076 ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext) 1077 .setId("id2") 1078 .setTitle("x") 1079 .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class)) 1080 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) 1081 .setRank(456) 1082 .build(); 1083 1084 mManager.addDynamicShortcuts(list(sorig, sorig2)); 1085 1086 // Dynamic shortcuts won't be backed up, so we need to pin it. 1087 setCaller(LAUNCHER_1, USER_0); 1088 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0); 1089 1090 // Do backup & restore. 1091 backupAndRestore(); 1092 1093 mService.handleUnlockUser(USER_0); // Load user-0. 1094 1095 ShortcutInfo si; 1096 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0); 1097 1098 assertEquals(CALLING_PACKAGE_1, si.getPackage()); 1099 assertEquals("id", si.getId()); 1100 assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); 1101 assertEquals(null, si.getIcon()); 1102 assertEquals(10, si.getTitleResId()); 1103 assertEquals("r10", si.getTitleResName()); 1104 assertEquals(11, si.getTextResId()); 1105 assertEquals("r11", si.getTextResName()); 1106 assertEquals(12, si.getDisabledMessageResourceId()); 1107 assertEquals("r12", si.getDisabledMessageResName()); 1108 assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); 1109 assertEquals("action", si.getIntent().getAction()); 1110 assertEquals("val", si.getIntent().getStringExtra("key")); 1111 assertEquals(0, si.getRank()); 1112 assertEquals(1, si.getExtras().getInt("k")); 1113 1114 assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags()); 1115 assertNull(si.getBitmapPath()); // No icon. 1116 assertEquals(0, si.getIconResourceId()); 1117 assertEquals(null, si.getIconResName()); 1118 1119 // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank. 1120 si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0); 1121 assertEquals(0, si.getRank()); 1122 } 1123 1124 private void checkShortcutInfoSaveAndLoad_intents(Intent intent) { 1125 assertTrue(mManager.setDynamicShortcuts(list( 1126 makeShortcutWithIntent("s1", intent)))); 1127 initService(); 1128 mService.handleUnlockUser(USER_0); 1129 1130 assertWith(getCallerShortcuts()) 1131 .haveIds("s1") 1132 .forShortcutWithId("s1", si -> { 1133 assertEquals(intent.getAction(), si.getIntent().getAction()); 1134 assertEquals(intent.getData(), si.getIntent().getData()); 1135 assertEquals(intent.getComponent(), si.getIntent().getComponent()); 1136 assertBundlesEqual(intent.getExtras(), si.getExtras()); 1137 }); 1138 } 1139 1140 public void testShortcutInfoSaveAndLoad_intents() { 1141 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW)); 1142 1143 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1144 1145 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN)); 1146 1147 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1148 1149 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW, 1150 Uri.parse("http://www.example.com/"))); 1151 1152 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1153 1154 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN, 1155 Uri.parse("http://www.example.com/"))); 1156 1157 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1158 1159 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW) 1160 .setComponent(new ComponentName("a", "b"))); 1161 1162 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1163 1164 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN) 1165 .setComponent(new ComponentName("a", "b"))); 1166 1167 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1168 1169 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW) 1170 .putExtras(makeBundle("a", "b"))); 1171 1172 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1173 1174 1175 checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN) 1176 .putExtras(makeBundle("a", "b"))); 1177 1178 mInjectedCurrentTimeMillis += INTERVAL; // reset throttling. 1179 } 1180 1181 public void testThrottling() { 1182 final ShortcutInfo si1 = makeShortcut("shortcut1"); 1183 1184 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1185 assertEquals(2, mManager.getRemainingCallCount()); 1186 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1187 1188 mInjectedCurrentTimeMillis++; 1189 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1190 assertEquals(1, mManager.getRemainingCallCount()); 1191 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1192 1193 mInjectedCurrentTimeMillis++; 1194 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1195 assertEquals(0, mManager.getRemainingCallCount()); 1196 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1197 1198 // Reached the max 1199 1200 mInjectedCurrentTimeMillis++; 1201 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1202 assertEquals(0, mManager.getRemainingCallCount()); 1203 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1204 1205 // Still throttled 1206 mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1; 1207 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1208 assertEquals(0, mManager.getRemainingCallCount()); 1209 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1210 1211 // Now it should work. 1212 mInjectedCurrentTimeMillis++; 1213 assertTrue(mManager.setDynamicShortcuts(list(si1))); // fail 1214 assertEquals(2, mManager.getRemainingCallCount()); 1215 assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime()); 1216 1217 mInjectedCurrentTimeMillis++; 1218 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1219 assertEquals(1, mManager.getRemainingCallCount()); 1220 assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime()); 1221 1222 mInjectedCurrentTimeMillis++; 1223 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1224 assertEquals(0, mManager.getRemainingCallCount()); 1225 assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime()); 1226 1227 mInjectedCurrentTimeMillis++; 1228 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1229 assertEquals(0, mManager.getRemainingCallCount()); 1230 assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime()); 1231 1232 // 4 hours later... 1233 mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL; 1234 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1235 assertEquals(2, mManager.getRemainingCallCount()); 1236 assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime()); 1237 1238 mInjectedCurrentTimeMillis++; 1239 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1240 assertEquals(1, mManager.getRemainingCallCount()); 1241 assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime()); 1242 1243 // Make sure getRemainingCallCount() itself gets reset without calling setDynamicShortcuts(). 1244 mInjectedCurrentTimeMillis = START_TIME + 8 * INTERVAL; 1245 assertEquals(3, mManager.getRemainingCallCount()); 1246 assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime()); 1247 1248 mInjectedCurrentTimeMillis++; 1249 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1250 assertEquals(2, mManager.getRemainingCallCount()); 1251 assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime()); 1252 } 1253 1254 public void testThrottling_rewind() { 1255 final ShortcutInfo si1 = makeShortcut("shortcut1"); 1256 1257 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1258 assertEquals(2, mManager.getRemainingCallCount()); 1259 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1260 1261 mInjectedCurrentTimeMillis = 12345; // Clock reset! 1262 1263 // Since the clock looks invalid, the counter shouldn't have reset. 1264 assertEquals(2, mManager.getRemainingCallCount()); 1265 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1266 1267 // Forward again. Still haven't reset yet. 1268 mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1; 1269 assertEquals(2, mManager.getRemainingCallCount()); 1270 assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime()); 1271 1272 // Now rewind -- this will reset the counters. 1273 mInjectedCurrentTimeMillis = START_TIME - 100000; 1274 assertEquals(3, mManager.getRemainingCallCount()); 1275 1276 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1277 assertEquals(2, mManager.getRemainingCallCount()); 1278 1279 // Forward again, should be reset now. 1280 mInjectedCurrentTimeMillis += INTERVAL; 1281 assertEquals(3, mManager.getRemainingCallCount()); 1282 } 1283 1284 public void testThrottling_perPackage() { 1285 final ShortcutInfo si1 = makeShortcut("shortcut1"); 1286 1287 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1288 assertEquals(2, mManager.getRemainingCallCount()); 1289 1290 mInjectedCurrentTimeMillis++; 1291 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1292 assertEquals(1, mManager.getRemainingCallCount()); 1293 1294 mInjectedCurrentTimeMillis++; 1295 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1296 assertEquals(0, mManager.getRemainingCallCount()); 1297 1298 // Reached the max 1299 1300 mInjectedCurrentTimeMillis++; 1301 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1302 1303 // Try from a different caller. 1304 mInjectedClientPackage = CALLING_PACKAGE_2; 1305 mInjectedCallingUid = CALLING_UID_2; 1306 1307 // Need to create a new one wit the updated package name. 1308 final ShortcutInfo si2 = makeShortcut("shortcut1"); 1309 1310 assertEquals(3, mManager.getRemainingCallCount()); 1311 1312 assertTrue(mManager.setDynamicShortcuts(list(si2))); 1313 assertEquals(2, mManager.getRemainingCallCount()); 1314 1315 mInjectedCurrentTimeMillis++; 1316 assertTrue(mManager.setDynamicShortcuts(list(si2))); 1317 assertEquals(1, mManager.getRemainingCallCount()); 1318 1319 // Back to the original caller, still throttled. 1320 mInjectedClientPackage = CALLING_PACKAGE_1; 1321 mInjectedCallingUid = CALLING_UID_1; 1322 1323 mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1; 1324 assertEquals(0, mManager.getRemainingCallCount()); 1325 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1326 assertEquals(0, mManager.getRemainingCallCount()); 1327 1328 // Now it should work. 1329 mInjectedCurrentTimeMillis++; 1330 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1331 1332 mInjectedCurrentTimeMillis++; 1333 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1334 1335 mInjectedCurrentTimeMillis++; 1336 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1337 1338 mInjectedCurrentTimeMillis++; 1339 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1340 1341 mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL; 1342 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1343 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1344 assertTrue(mManager.setDynamicShortcuts(list(si1))); 1345 assertFalse(mManager.setDynamicShortcuts(list(si1))); 1346 1347 mInjectedClientPackage = CALLING_PACKAGE_2; 1348 mInjectedCallingUid = CALLING_UID_2; 1349 1350 assertEquals(3, mManager.getRemainingCallCount()); 1351 1352 assertTrue(mManager.setDynamicShortcuts(list(si2))); 1353 assertTrue(mManager.setDynamicShortcuts(list(si2))); 1354 assertTrue(mManager.setDynamicShortcuts(list(si2))); 1355 assertFalse(mManager.setDynamicShortcuts(list(si2))); 1356 } 1357 1358 public void testThrottling_localeChanges() { 1359 prepareCrossProfileDataSet(); 1360 1361 dumpsysOnLogcat("Before save & load"); 1362 1363 mService.saveDirtyInfo(); 1364 initService(); 1365 1366 mInjectedLocale = Locale.CHINA; 1367 mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED)); 1368 1369 // Note at this point only user-0 is loaded, and the counters are reset for this user, 1370 // but it will work for other users too because we check the locale change at any 1371 // API entry point. 1372 1373 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1374 assertEquals(3, mManager.getRemainingCallCount()); 1375 }); 1376 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1377 assertEquals(3, mManager.getRemainingCallCount()); 1378 }); 1379 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1380 assertEquals(3, mManager.getRemainingCallCount()); 1381 }); 1382 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1383 assertEquals(3, mManager.getRemainingCallCount()); 1384 }); 1385 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1386 assertEquals(3, mManager.getRemainingCallCount()); 1387 }); 1388 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1389 assertEquals(3, mManager.getRemainingCallCount()); 1390 }); 1391 1392 // Make sure even if we receive ACTION_LOCALE_CHANGED, if the locale hasn't actually 1393 // changed, we don't reset throttling. 1394 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1395 mManager.updateShortcuts(list()); 1396 assertEquals(2, mManager.getRemainingCallCount()); 1397 }); 1398 1399 mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED)); 1400 1401 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1402 assertEquals(2, mManager.getRemainingCallCount()); // Still 2. 1403 }); 1404 1405 mService.saveDirtyInfo(); 1406 initService(); 1407 1408 // The locale should be persisted, so it still shouldn't reset throttling. 1409 mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED)); 1410 1411 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1412 assertEquals(2, mManager.getRemainingCallCount()); // Still 2. 1413 }); 1414 } 1415 1416 public void testThrottling_foreground() throws Exception { 1417 prepareCrossProfileDataSet(); 1418 1419 dumpsysOnLogcat("Before save & load"); 1420 1421 mService.saveDirtyInfo(); 1422 initService(); 1423 1424 // We need to update the current time from time to time, since some of the internal checks 1425 // rely on the time being correctly incremented. 1426 mInjectedCurrentTimeMillis++; 1427 1428 // First, all packages have less than 3 (== initial value) remaining calls. 1429 1430 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1431 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1432 }); 1433 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1434 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1435 }); 1436 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1437 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1438 }); 1439 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1440 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1441 }); 1442 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1443 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1444 }); 1445 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1446 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1447 }); 1448 1449 mInjectedCurrentTimeMillis++; 1450 1451 // State changed, but not foreground, so no resetting. 1452 mService.mUidObserver.onUidStateChanged( 1453 CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING); 1454 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1455 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1456 }); 1457 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1458 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1459 }); 1460 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1461 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1462 }); 1463 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1464 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1465 }); 1466 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1467 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1468 }); 1469 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1470 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1471 }); 1472 1473 mInjectedCurrentTimeMillis++; 1474 1475 // State changed, package1 foreground, reset. 1476 mService.mUidObserver.onUidStateChanged( 1477 CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 1478 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1479 assertEquals(3, mManager.getRemainingCallCount()); 1480 }); 1481 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1482 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1483 }); 1484 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1485 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1486 }); 1487 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1488 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1489 }); 1490 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1491 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1492 }); 1493 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1494 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1495 }); 1496 mService.mUidObserver.onUidStateChanged( 1497 CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING); 1498 1499 mInjectedCurrentTimeMillis++; 1500 1501 // Different app comes to foreground briefly, and goes back to background. 1502 // Now, make sure package 2's counter is reset, even in this case. 1503 mService.mUidObserver.onUidStateChanged( 1504 CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 1505 mService.mUidObserver.onUidStateChanged( 1506 CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING); 1507 1508 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1509 assertEquals(3, mManager.getRemainingCallCount()); 1510 }); 1511 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1512 assertEquals(3, mManager.getRemainingCallCount()); 1513 }); 1514 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1515 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1516 }); 1517 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1518 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1519 }); 1520 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1521 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1522 }); 1523 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1524 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1525 }); 1526 1527 mInjectedCurrentTimeMillis++; 1528 1529 // Do the same thing one more time. This would catch the bug with mixuing up 1530 // the current time and the elapsed time. 1531 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1532 mManager.updateShortcuts(list(makeShortcut("s"))); 1533 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1534 }); 1535 1536 mService.mUidObserver.onUidStateChanged( 1537 CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 1538 mService.mUidObserver.onUidStateChanged( 1539 CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING); 1540 1541 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1542 assertEquals(3, mManager.getRemainingCallCount()); 1543 }); 1544 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1545 assertEquals(3, mManager.getRemainingCallCount()); 1546 }); 1547 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1548 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1549 }); 1550 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1551 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1552 }); 1553 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1554 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1555 }); 1556 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1557 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1558 }); 1559 1560 mInjectedCurrentTimeMillis++; 1561 1562 // Package 1 on user-10 comes to foreground. 1563 // Now, also try calling some APIs and make sure foreground apps don't get throttled. 1564 mService.mUidObserver.onUidStateChanged( 1565 UserHandle.getUid(USER_10, CALLING_UID_1), 1566 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 1567 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1568 assertEquals(3, mManager.getRemainingCallCount()); 1569 1570 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1571 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1572 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1573 1574 assertEquals(0, mManager.getRemainingCallCount()); 1575 }); 1576 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1577 assertEquals(3, mManager.getRemainingCallCount()); 1578 1579 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1580 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1581 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1582 1583 assertEquals(0, mManager.getRemainingCallCount()); 1584 }); 1585 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1586 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1587 1588 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1589 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1590 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1591 1592 assertEquals(0, mManager.getRemainingCallCount()); 1593 }); 1594 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1595 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1596 1597 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1598 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1599 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1600 1601 assertEquals(0, mManager.getRemainingCallCount()); 1602 }); 1603 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1604 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1605 1606 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1607 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1608 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1609 1610 assertEquals(0, mManager.getRemainingCallCount()); 1611 }); 1612 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1613 assertEquals(3, mManager.getRemainingCallCount()); 1614 1615 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1616 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1617 mManager.setDynamicShortcuts(list(makeShortcut("s"))); 1618 1619 assertEquals(3, mManager.getRemainingCallCount()); // Still 3! 1620 }); 1621 } 1622 1623 1624 public void testThrottling_resetByInternalCall() throws Exception { 1625 prepareCrossProfileDataSet(); 1626 1627 dumpsysOnLogcat("Before save & load"); 1628 1629 mService.saveDirtyInfo(); 1630 initService(); 1631 1632 // First, all packages have less than 3 (== initial value) remaining calls. 1633 1634 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1635 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1636 }); 1637 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1638 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1639 }); 1640 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1641 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1642 }); 1643 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1644 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1645 }); 1646 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1647 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1648 }); 1649 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1650 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1651 }); 1652 1653 // Simulate a call from sys UI. 1654 mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING); 1655 mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0); 1656 1657 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1658 assertEquals(3, mManager.getRemainingCallCount()); 1659 }); 1660 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1661 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1662 }); 1663 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1664 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1665 }); 1666 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1667 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1668 }); 1669 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1670 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1671 }); 1672 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1673 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1674 }); 1675 1676 mManager.onApplicationActive(CALLING_PACKAGE_3, USER_0); 1677 1678 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1679 assertEquals(3, mManager.getRemainingCallCount()); 1680 }); 1681 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1682 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1683 }); 1684 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1685 assertEquals(3, mManager.getRemainingCallCount()); 1686 }); 1687 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1688 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1689 }); 1690 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1691 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1692 }); 1693 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1694 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1695 }); 1696 1697 mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10); 1698 1699 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1700 assertEquals(3, mManager.getRemainingCallCount()); 1701 }); 1702 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1703 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1704 }); 1705 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1706 assertEquals(3, mManager.getRemainingCallCount()); 1707 }); 1708 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1709 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1710 }); 1711 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1712 MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); 1713 }); 1714 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1715 assertEquals(3, mManager.getRemainingCallCount()); 1716 }); 1717 } 1718 1719 public void testReportShortcutUsed() { 1720 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1721 reset(mMockUsageStatsManagerInternal); 1722 1723 // Report with an nonexistent shortcut. 1724 mManager.reportShortcutUsed("s1"); 1725 verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( 1726 anyString(), anyString(), anyInt()); 1727 1728 // Publish s2, but s1 still doesn't exist. 1729 mManager.setDynamicShortcuts(list(makeShortcut("s2"))); 1730 mManager.reportShortcutUsed("s1"); 1731 verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( 1732 anyString(), anyString(), anyInt()); 1733 1734 mManager.reportShortcutUsed("s2"); 1735 verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( 1736 eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_10)); 1737 1738 }); 1739 runWithCaller(CALLING_PACKAGE_2, USER_10, () -> { 1740 // Try with a different package. 1741 reset(mMockUsageStatsManagerInternal); 1742 1743 // Report with an nonexistent shortcut. 1744 mManager.reportShortcutUsed("s2"); 1745 verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( 1746 anyString(), anyString(), anyInt()); 1747 1748 // Publish s2, but s1 still doesn't exist. 1749 mManager.setDynamicShortcuts(list(makeShortcut("s3"))); 1750 mManager.reportShortcutUsed("s2"); 1751 verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( 1752 anyString(), anyString(), anyInt()); 1753 1754 mManager.reportShortcutUsed("s3"); 1755 verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( 1756 eq(CALLING_PACKAGE_2), eq("s3"), eq(USER_10)); 1757 1758 }); 1759 } 1760 1761 // Test for a ShortcutInfo method. 1762 public void testGetResourcePackageName() { 1763 assertEquals(null, ShortcutInfo.getResourcePackageName("")); 1764 assertEquals(null, ShortcutInfo.getResourcePackageName("abc")); 1765 assertEquals("p", ShortcutInfo.getResourcePackageName("p:")); 1766 assertEquals("p", ShortcutInfo.getResourcePackageName("p:xx")); 1767 assertEquals("pac", ShortcutInfo.getResourcePackageName("pac:")); 1768 } 1769 1770 // Test for a ShortcutInfo method. 1771 public void testGetResourceTypeName() { 1772 assertEquals(null, ShortcutInfo.getResourceTypeName("")); 1773 assertEquals(null, ShortcutInfo.getResourceTypeName(":")); 1774 assertEquals(null, ShortcutInfo.getResourceTypeName("/")); 1775 assertEquals(null, ShortcutInfo.getResourceTypeName("/:")); 1776 assertEquals("a", ShortcutInfo.getResourceTypeName(":a/")); 1777 assertEquals("type", ShortcutInfo.getResourceTypeName("xxx:type/yyy")); 1778 } 1779 1780 // Test for a ShortcutInfo method. 1781 public void testGetResourceTypeAndEntryName() { 1782 assertEquals(null, ShortcutInfo.getResourceTypeAndEntryName("")); 1783 assertEquals(null, ShortcutInfo.getResourceTypeAndEntryName("abc")); 1784 assertEquals("", ShortcutInfo.getResourceTypeAndEntryName("p:")); 1785 assertEquals("x", ShortcutInfo.getResourceTypeAndEntryName(":x")); 1786 assertEquals("x", ShortcutInfo.getResourceTypeAndEntryName("p:x")); 1787 assertEquals("xyz", ShortcutInfo.getResourceTypeAndEntryName("pac:xyz")); 1788 } 1789 1790 // Test for a ShortcutInfo method. 1791 public void testGetResourceEntryName() { 1792 assertEquals(null, ShortcutInfo.getResourceEntryName("")); 1793 assertEquals(null, ShortcutInfo.getResourceEntryName("ab:")); 1794 assertEquals("", ShortcutInfo.getResourceEntryName("/")); 1795 assertEquals("abc", ShortcutInfo.getResourceEntryName("/abc")); 1796 assertEquals("abc", ShortcutInfo.getResourceEntryName("xyz/abc")); 1797 } 1798 1799 // Test for a ShortcutInfo method. 1800 public void testLookUpResourceName_systemResources() { 1801 // For android system resources, lookUpResourceName will simply return the value as a 1802 // string, regardless of "withType". 1803 final Resources res = getTestContext().getResources(); 1804 1805 assertEquals("" + android.R.string.cancel, ShortcutInfo.lookUpResourceName(res, 1806 android.R.string.cancel, true, getTestContext().getPackageName())); 1807 assertEquals("" + android.R.drawable.alert_dark_frame, ShortcutInfo.lookUpResourceName(res, 1808 android.R.drawable.alert_dark_frame, true, getTestContext().getPackageName())); 1809 assertEquals("" + android.R.string.cancel, ShortcutInfo.lookUpResourceName(res, 1810 android.R.string.cancel, false, getTestContext().getPackageName())); 1811 } 1812 1813 public void testLookUpResourceName_appResources() { 1814 final Resources res = getTestContext().getResources(); 1815 1816 assertEquals("shortcut_text1", ShortcutInfo.lookUpResourceName(res, 1817 R.string.shortcut_text1, false, getTestContext().getPackageName())); 1818 assertEquals("string/shortcut_text1", ShortcutInfo.lookUpResourceName(res, 1819 R.string.shortcut_text1, true, getTestContext().getPackageName())); 1820 1821 assertEquals("black_16x64", ShortcutInfo.lookUpResourceName(res, 1822 R.drawable.black_16x64, false, getTestContext().getPackageName())); 1823 assertEquals("drawable/black_16x64", ShortcutInfo.lookUpResourceName(res, 1824 R.drawable.black_16x64, true, getTestContext().getPackageName())); 1825 } 1826 1827 // Test for a ShortcutInfo method. 1828 public void testLookUpResourceId_systemResources() { 1829 final Resources res = getTestContext().getResources(); 1830 1831 assertEquals(android.R.string.cancel, ShortcutInfo.lookUpResourceId(res, 1832 "" + android.R.string.cancel, null, 1833 getTestContext().getPackageName())); 1834 assertEquals(android.R.drawable.alert_dark_frame, ShortcutInfo.lookUpResourceId(res, 1835 "" + android.R.drawable.alert_dark_frame, null, 1836 getTestContext().getPackageName())); 1837 } 1838 1839 // Test for a ShortcutInfo method. 1840 public void testLookUpResourceId_appResources() { 1841 final Resources res = getTestContext().getResources(); 1842 1843 assertEquals(R.string.shortcut_text1, 1844 ShortcutInfo.lookUpResourceId(res, "shortcut_text1", "string", 1845 getTestContext().getPackageName())); 1846 1847 assertEquals(R.string.shortcut_text1, 1848 ShortcutInfo.lookUpResourceId(res, "string/shortcut_text1", null, 1849 getTestContext().getPackageName())); 1850 1851 assertEquals(R.drawable.black_16x64, 1852 ShortcutInfo.lookUpResourceId(res, "black_16x64", "drawable", 1853 getTestContext().getPackageName())); 1854 1855 assertEquals(R.drawable.black_16x64, 1856 ShortcutInfo.lookUpResourceId(res, "drawable/black_16x64", null, 1857 getTestContext().getPackageName())); 1858 } 1859 1860 public void testDumpCheckin() throws IOException { 1861 prepareCrossProfileDataSet(); 1862 1863 // prepareCrossProfileDataSet() doesn't set any icons, so do set here. 1864 final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32); 1865 final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64); 1866 final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( 1867 getTestContext().getResources(), R.drawable.black_32x32)); 1868 final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource( 1869 getTestContext().getResources(), R.drawable.black_64x64)); 1870 1871 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1872 assertTrue(mManager.setDynamicShortcuts(list( 1873 makeShortcutWithIcon("res32x32", res32x32), 1874 makeShortcutWithIcon("res64x64", res64x64), 1875 makeShortcutWithIcon("bmp32x32", bmp32x32), 1876 makeShortcutWithIcon("bmp64x64", bmp64x64)))); 1877 }); 1878 // We can't predict the compressed bitmap sizes, so get the real sizes here. 1879 final long bitmapTotal = 1880 new File(getPackageShortcut(CALLING_PACKAGE_2, "bmp32x32", USER_0) 1881 .getBitmapPath()).length() + 1882 new File(getPackageShortcut(CALLING_PACKAGE_2, "bmp64x64", USER_0) 1883 .getBitmapPath()).length(); 1884 1885 // Read the expected output and inject the bitmap size. 1886 final String expected = readTestAsset("shortcut/dumpsys_expected.txt") 1887 .replace("***BITMAP_SIZE***", String.valueOf(bitmapTotal)); 1888 1889 assertEquals(expected, dumpCheckin()); 1890 } 1891 1892 public void testDumpsysNoPermission() { 1893 assertExpectException(SecurityException.class, "android.permission.DUMP", 1894 () -> mService.dump(null, new PrintWriter(new StringWriter()), null)); 1895 1896 // System can call it without the permission. 1897 runWithSystemUid(() -> { 1898 mService.dump(null, new PrintWriter(new StringWriter()), null); 1899 }); 1900 } 1901} 1902