BaseShortcutManagerTest.java revision 2d895c3efd625e09e9f2cc4d0c7131b34f52f154
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.cloneShortcutList; 19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet; 20import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; 21import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle; 22import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set; 23 24import static org.mockito.Matchers.any; 25import static org.mockito.Matchers.anyInt; 26import static org.mockito.Matchers.anyString; 27import static org.mockito.Matchers.eq; 28import static org.mockito.Mockito.doAnswer; 29import static org.mockito.Mockito.mock; 30import static org.mockito.Mockito.reset; 31import static org.mockito.Mockito.spy; 32import static org.mockito.Mockito.times; 33import static org.mockito.Mockito.verify; 34import static org.mockito.Mockito.when; 35 36import android.annotation.NonNull; 37import android.annotation.UserIdInt; 38import android.app.Activity; 39import android.app.ActivityManager; 40import android.app.ActivityManagerInternal; 41import android.app.IUidObserver; 42import android.app.usage.UsageStatsManagerInternal; 43import android.content.ActivityNotFoundException; 44import android.content.BroadcastReceiver; 45import android.content.ComponentName; 46import android.content.Context; 47import android.content.Intent; 48import android.content.IntentFilter; 49import android.content.IntentSender; 50import android.content.pm.ActivityInfo; 51import android.content.pm.ApplicationInfo; 52import android.content.pm.ILauncherApps; 53import android.content.pm.LauncherApps; 54import android.content.pm.LauncherApps.ShortcutQuery; 55import android.content.pm.PackageInfo; 56import android.content.pm.PackageManager; 57import android.content.pm.PackageManagerInternal; 58import android.content.pm.ResolveInfo; 59import android.content.pm.ShortcutInfo; 60import android.content.pm.ShortcutManager; 61import android.content.pm.ShortcutServiceInternal; 62import android.content.pm.Signature; 63import android.content.pm.UserInfo; 64import android.content.res.Resources; 65import android.content.res.XmlResourceParser; 66import android.graphics.drawable.Icon; 67import android.net.Uri; 68import android.os.Bundle; 69import android.os.FileUtils; 70import android.os.Handler; 71import android.os.Looper; 72import android.os.PersistableBundle; 73import android.os.Process; 74import android.os.UserHandle; 75import android.os.UserManager; 76import android.test.InstrumentationTestCase; 77import android.test.mock.MockContext; 78import android.util.ArrayMap; 79import android.util.Log; 80import android.util.Pair; 81 82import com.android.internal.util.Preconditions; 83import com.android.server.LocalServices; 84import com.android.server.SystemService; 85import com.android.server.pm.LauncherAppsService.LauncherAppsImpl; 86import com.android.server.pm.ShortcutUser.PackageWithUser; 87 88import org.junit.Assert; 89import org.mockito.ArgumentCaptor; 90import org.mockito.invocation.InvocationOnMock; 91import org.mockito.stubbing.Answer; 92 93import java.io.BufferedReader; 94import java.io.ByteArrayOutputStream; 95import java.io.File; 96import java.io.FileReader; 97import java.io.IOException; 98import java.io.InputStreamReader; 99import java.io.PrintWriter; 100import java.util.ArrayList; 101import java.util.HashMap; 102import java.util.HashSet; 103import java.util.LinkedHashMap; 104import java.util.List; 105import java.util.Locale; 106import java.util.Map; 107import java.util.Set; 108import java.util.function.BiFunction; 109import java.util.function.BiPredicate; 110import java.util.function.Consumer; 111import java.util.function.Function; 112 113public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { 114 protected static final String TAG = "ShortcutManagerTest"; 115 116 protected static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true 117 118 /** 119 * Whether to enable dump or not. Should be only true when debugging to avoid bugs where 120 * dump affecting the behavior. 121 */ 122 protected static final boolean ENABLE_DUMP = false // DO NOT SUBMIT WITH true 123 || DUMP_IN_TEARDOWN || ShortcutService.DEBUG; 124 125 protected static final String[] EMPTY_STRINGS = new String[0]; // Just for readability. 126 127 protected static final String MAIN_ACTIVITY_CLASS = "MainActivity"; 128 protected static final String PIN_CONFIRM_ACTIVITY_CLASS = "PinConfirmActivity"; 129 130 // public for mockito 131 public class BaseContext extends MockContext { 132 @Override 133 public Object getSystemService(String name) { 134 switch (name) { 135 case Context.USER_SERVICE: 136 return mMockUserManager; 137 } 138 throw new UnsupportedOperationException(); 139 } 140 141 @Override 142 public String getSystemServiceName(Class<?> serviceClass) { 143 return getTestContext().getSystemServiceName(serviceClass); 144 } 145 146 @Override 147 public PackageManager getPackageManager() { 148 return mMockPackageManager; 149 } 150 151 @Override 152 public Resources getResources() { 153 return getTestContext().getResources(); 154 } 155 156 @Override 157 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, 158 IntentFilter filter, String broadcastPermission, Handler scheduler) { 159 // ignore. 160 return null; 161 } 162 163 @Override 164 public void unregisterReceiver(BroadcastReceiver receiver) { 165 // ignore. 166 } 167 168 @Override 169 public void startActivityAsUser(Intent intent, UserHandle user) { 170 // ignore, use spy to intercept it. 171 } 172 } 173 174 /** Context used in the client side */ 175 public class ClientContext extends BaseContext { 176 @Override 177 public String getPackageName() { 178 return mInjectedClientPackage; 179 } 180 181 @Override 182 public int getUserId() { 183 return getCallingUserId(); 184 } 185 } 186 187 /** Context used in the service side */ 188 public class ServiceContext extends BaseContext { 189 long injectClearCallingIdentity() { 190 final int prevCallingUid = mInjectedCallingUid; 191 mInjectedCallingUid = Process.SYSTEM_UID; 192 return prevCallingUid; 193 } 194 195 void injectRestoreCallingIdentity(long token) { 196 mInjectedCallingUid = (int) token; 197 } 198 199 @Override 200 public int getUserId() { 201 return UserHandle.USER_SYSTEM; 202 } 203 204 public PackageInfo injectGetActivitiesWithMetadata( 205 String packageName, @UserIdInt int userId) { 206 return BaseShortcutManagerTest.this.injectGetActivitiesWithMetadata(packageName, userId); 207 } 208 209 public XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { 210 return BaseShortcutManagerTest.this.injectXmlMetaData(activityInfo, key); 211 } 212 213 public void sendIntentSender(IntentSender intent) { 214 // Placeholder for spying. 215 } 216 } 217 218 /** ShortcutService with injection override methods. */ 219 protected final class ShortcutServiceTestable extends ShortcutService { 220 final ServiceContext mContext; 221 IUidObserver mUidObserver; 222 223 public ShortcutServiceTestable(ServiceContext context, Looper looper) { 224 super(context, looper, /* onyForPackageManagerApis */ false); 225 mContext = context; 226 } 227 228 @Override 229 public String injectGetLocaleTagsForUser(@UserIdInt int userId) { 230 return mInjectedLocale.toLanguageTag(); 231 } 232 233 @Override 234 boolean injectShouldPerformVerification() { 235 return true; // Always verify during unit tests. 236 } 237 238 @Override 239 String injectShortcutManagerConstants() { 240 return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + "," 241 + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + "," 242 + ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=" 243 + MAX_UPDATES_PER_INTERVAL + "," 244 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + "," 245 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=" 246 + MAX_ICON_DIMENSION_LOWRAM + "," 247 + ConfigConstants.KEY_ICON_FORMAT + "=PNG," 248 + ConfigConstants.KEY_ICON_QUALITY + "=100"; 249 } 250 251 @Override 252 long injectClearCallingIdentity() { 253 return mContext.injectClearCallingIdentity(); 254 } 255 256 @Override 257 void injectRestoreCallingIdentity(long token) { 258 mContext.injectRestoreCallingIdentity(token); 259 } 260 261 @Override 262 int injectDipToPixel(int dip) { 263 return dip; 264 } 265 266 @Override 267 long injectCurrentTimeMillis() { 268 return mInjectedCurrentTimeMillis; 269 } 270 271 @Override 272 long injectElapsedRealtime() { 273 // TODO This should be kept separately from mInjectedCurrentTimeMillis, since 274 // this should increase even if we rewind mInjectedCurrentTimeMillis in some tests. 275 return mInjectedCurrentTimeMillis - START_TIME; 276 } 277 278 @Override 279 int injectBinderCallingUid() { 280 return mInjectedCallingUid; 281 } 282 283 @Override 284 int injectGetPackageUid(String packageName, int userId) { 285 return getInjectedPackageInfo(packageName, userId, false).applicationInfo.uid; 286 } 287 288 @Override 289 File injectSystemDataPath() { 290 return new File(mInjectedFilePathRoot, "system"); 291 } 292 293 @Override 294 File injectUserDataPath(@UserIdInt int userId) { 295 return new File(mInjectedFilePathRoot, "user-" + userId); 296 } 297 298 @Override 299 void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) { 300 // Can't check 301 } 302 303 @Override 304 boolean injectIsLowRamDevice() { 305 return mInjectedIsLowRamDevice; 306 } 307 308 @Override 309 void injectRegisterUidObserver(IUidObserver observer, int which) { 310 mUidObserver = observer; 311 } 312 313 @Override 314 boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) { 315 return mDefaultLauncherChecker.test(callingPackage, userId); 316 } 317 318 @Override 319 ComponentName getDefaultLauncher(@UserIdInt int userId) { 320 final ComponentName activity = mDefaultLauncher.get(userId); 321 if (activity != null) { 322 return activity; 323 } 324 return super.getDefaultLauncher(userId); 325 } 326 327 @Override 328 PackageInfo injectPackageInfoWithUninstalled(String packageName, @UserIdInt int userId, 329 boolean getSignatures) { 330 return getInjectedPackageInfo(packageName, userId, getSignatures); 331 } 332 333 @Override 334 ApplicationInfo injectApplicationInfoWithUninstalled( 335 String packageName, @UserIdInt int userId) { 336 PackageInfo pi = injectPackageInfoWithUninstalled( 337 packageName, userId, /* getSignatures= */ false); 338 return pi != null ? pi.applicationInfo : null; 339 } 340 341 @Override 342 List<PackageInfo> injectGetPackagesWithUninstalled(@UserIdInt int userId) { 343 return BaseShortcutManagerTest.this.getInstalledPackagesWithUninstalled(userId); 344 } 345 346 @Override 347 ActivityInfo injectGetActivityInfoWithMetadataWithUninstalled(ComponentName activity, 348 @UserIdInt int userId) { 349 final PackageInfo pi = mContext.injectGetActivitiesWithMetadata( 350 activity.getPackageName(), userId); 351 if (pi == null || pi.activities == null) { 352 return null; 353 } 354 for (ActivityInfo ai : pi.activities) { 355 if (!mEnabledActivityChecker.test(ai.getComponentName(), userId)) { 356 continue; 357 } 358 if (activity.equals(ai.getComponentName())) { 359 return ai; 360 } 361 } 362 return null; 363 } 364 365 @Override 366 boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) { 367 if (!mEnabledActivityChecker.test(activity, userId)) { 368 return false; 369 } 370 return mMainActivityChecker.test(activity, userId); 371 } 372 373 @Override 374 List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) { 375 final PackageInfo pi = mContext.injectGetActivitiesWithMetadata( 376 packageName, userId); 377 if (pi == null || pi.activities == null) { 378 return null; 379 } 380 final ArrayList<ResolveInfo> ret = new ArrayList<>(pi.activities.length); 381 for (int i = 0; i < pi.activities.length; i++) { 382 if (!mEnabledActivityChecker.test(pi.activities[i].getComponentName(), userId)) { 383 continue; 384 } 385 final ResolveInfo ri = new ResolveInfo(); 386 ri.activityInfo = pi.activities[i]; 387 ret.add(ri); 388 } 389 390 return ret; 391 } 392 393 @Override 394 ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) { 395 return mMainActivityFetcher.apply(packageName, userId); 396 } 397 398 @Override 399 ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName, 400 int launcherUserId) { 401 return mPinConfirmActivityFetcher.apply(launcherPackageName, launcherUserId); 402 } 403 404 @Override 405 boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) { 406 assertNotNull(activity); 407 return mEnabledActivityChecker.test(activity, userId); 408 } 409 410 @Override 411 XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { 412 return mContext.injectXmlMetaData(activityInfo, key); 413 } 414 415 @Override 416 void injectPostToHandler(Runnable r) { 417 runOnHandler(r); 418 } 419 420 @Override 421 void injectRunOnNewThread(Runnable r) { 422 runOnHandler(r); 423 } 424 425 @Override 426 void injectEnforceCallingPermission(String permission, String message) { 427 if (!mCallerPermissions.contains(permission)) { 428 throw new SecurityException("Missing permission: " + permission); 429 } 430 } 431 432 @Override 433 boolean injectIsSafeModeEnabled() { 434 return mSafeMode; 435 } 436 437 @Override 438 String injectBuildFingerprint() { 439 return mInjectedBuildFingerprint; 440 } 441 442 @Override 443 void injectSendIntentSender(IntentSender intent) { 444 mContext.sendIntentSender(intent); 445 } 446 447 @Override 448 void wtf(String message, Throwable th) { 449 // During tests, WTF is fatal. 450 fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th)); 451 } 452 453 @Override 454 void verifyError() { 455 fail("Verify error"); 456 } 457 } 458 459 /** ShortcutManager with injection override methods. */ 460 protected class ShortcutManagerTestable extends ShortcutManager { 461 public ShortcutManagerTestable(Context context, ShortcutServiceTestable service) { 462 super(context, service); 463 } 464 465 @Override 466 protected int injectMyUserId() { 467 return UserHandle.getUserId(mInjectedCallingUid); 468 } 469 470 @Override 471 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { 472 // Note to simulate the binder RPC, we need to clone the incoming arguments. 473 // Otherwise bad things will happen because they're mutable. 474 return super.setDynamicShortcuts(cloneShortcutList(shortcutInfoList)); 475 } 476 477 @Override 478 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { 479 // Note to simulate the binder RPC, we need to clone the incoming arguments. 480 return super.addDynamicShortcuts(cloneShortcutList(shortcutInfoList)); 481 } 482 483 @Override 484 public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) { 485 // Note to simulate the binder RPC, we need to clone the incoming arguments. 486 return super.updateShortcuts(cloneShortcutList(shortcutInfoList)); 487 } 488 } 489 490 protected class LauncherAppImplTestable extends LauncherAppsImpl { 491 final ServiceContext mContext; 492 493 public LauncherAppImplTestable(ServiceContext context) { 494 super(context); 495 mContext = context; 496 } 497 498 @Override 499 public void verifyCallingPackage(String callingPackage) { 500 // SKIP 501 } 502 503 @Override 504 void postToPackageMonitorHandler(Runnable r) { 505 runOnHandler(r); 506 } 507 508 @Override 509 int injectBinderCallingUid() { 510 return mInjectedCallingUid; 511 } 512 513 @Override 514 long injectClearCallingIdentity() { 515 final int prevCallingUid = mInjectedCallingUid; 516 mInjectedCallingUid = Process.SYSTEM_UID; 517 return prevCallingUid; 518 } 519 520 @Override 521 void injectRestoreCallingIdentity(long token) { 522 mInjectedCallingUid = (int) token; 523 } 524 } 525 526 protected class LauncherAppsTestable extends LauncherApps { 527 public LauncherAppsTestable(Context context, ILauncherApps service) { 528 super(context, service); 529 } 530 } 531 532 public static class ShortcutActivity extends Activity { 533 } 534 535 public static class ShortcutActivity2 extends Activity { 536 } 537 538 public static class ShortcutActivity3 extends Activity { 539 } 540 541 protected Looper mLooper; 542 protected Handler mHandler; 543 544 protected ServiceContext mServiceContext; 545 protected ClientContext mClientContext; 546 547 protected ShortcutServiceTestable mService; 548 protected ShortcutManagerTestable mManager; 549 protected ShortcutServiceInternal mInternal; 550 551 protected LauncherAppImplTestable mLauncherAppImpl; 552 553 // LauncherApps has per-instace state, so we need a differnt instance for each launcher. 554 protected final Map<Pair<Integer, String>, LauncherAppsTestable> 555 mLauncherAppsMap = new HashMap<>(); 556 protected LauncherAppsTestable mLauncherApps; // Current one 557 558 protected File mInjectedFilePathRoot; 559 560 protected boolean mSafeMode; 561 562 protected long mInjectedCurrentTimeMillis; 563 564 protected boolean mInjectedIsLowRamDevice; 565 566 protected Locale mInjectedLocale = Locale.ENGLISH; 567 568 protected int mInjectedCallingUid; 569 protected String mInjectedClientPackage; 570 571 protected Map<String, PackageInfo> mInjectedPackages; 572 573 protected Set<PackageWithUser> mUninstalledPackages; 574 protected Set<String> mSystemPackages; 575 576 protected PackageManager mMockPackageManager; 577 protected PackageManagerInternal mMockPackageManagerInternal; 578 protected UserManager mMockUserManager; 579 protected UsageStatsManagerInternal mMockUsageStatsManagerInternal; 580 protected ActivityManagerInternal mMockActivityManagerInternal; 581 582 protected static final String CALLING_PACKAGE_1 = "com.android.test.1"; 583 protected static final int CALLING_UID_1 = 10001; 584 585 protected static final String CALLING_PACKAGE_2 = "com.android.test.2"; 586 protected static final int CALLING_UID_2 = 10002; 587 588 protected static final String CALLING_PACKAGE_3 = "com.android.test.3"; 589 protected static final int CALLING_UID_3 = 10003; 590 591 protected static final String CALLING_PACKAGE_4 = "com.android.test.4"; 592 protected static final int CALLING_UID_4 = 10004; 593 594 protected static final String LAUNCHER_1 = "com.android.launcher.1"; 595 protected static final int LAUNCHER_UID_1 = 10011; 596 597 protected static final String LAUNCHER_2 = "com.android.launcher.2"; 598 protected static final int LAUNCHER_UID_2 = 10012; 599 600 protected static final String LAUNCHER_3 = "com.android.launcher.3"; 601 protected static final int LAUNCHER_UID_3 = 10013; 602 603 protected static final String LAUNCHER_4 = "com.android.launcher.4"; 604 protected static final int LAUNCHER_UID_4 = 10014; 605 606 protected static final int USER_0 = UserHandle.USER_SYSTEM; 607 protected static final int USER_10 = 10; 608 protected static final int USER_11 = 11; 609 protected static final int USER_P0 = 20; // profile of user 0 610 611 protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0); 612 protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10); 613 protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11); 614 protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0); 615 616 protected static final UserInfo USER_INFO_0 = withProfileGroupId( 617 new UserInfo(USER_0, "user0", 618 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 0); 619 620 protected static final UserInfo USER_INFO_10 = 621 new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED); 622 623 protected static final UserInfo USER_INFO_11 = 624 new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED); 625 626 protected static final UserInfo USER_INFO_P0 = withProfileGroupId( 627 new UserInfo(USER_P0, "userP0", 628 UserInfo.FLAG_MANAGED_PROFILE), 0); 629 630 protected BiPredicate<String, Integer> mDefaultLauncherChecker = 631 (callingPackage, userId) -> 632 LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage) 633 || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage); 634 635 private final Map<Integer, ComponentName> mDefaultLauncher = new ArrayMap<>(); 636 637 protected BiPredicate<ComponentName, Integer> mMainActivityChecker = 638 (activity, userId) -> true; 639 640 protected BiFunction<String, Integer, ComponentName> mMainActivityFetcher = 641 (packageName, userId) -> new ComponentName(packageName, MAIN_ACTIVITY_CLASS); 642 643 protected BiFunction<String, Integer, ComponentName> mPinConfirmActivityFetcher = 644 (packageName, userId) -> new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS); 645 646 protected BiPredicate<ComponentName, Integer> mEnabledActivityChecker 647 = (activity, userId) -> true; // all activities are enabled. 648 649 protected static final long START_TIME = 1440000000101L; 650 651 protected static final long INTERVAL = 10000; 652 653 protected static final int MAX_SHORTCUTS = 10; 654 655 protected static final int MAX_UPDATES_PER_INTERVAL = 3; 656 657 protected static final int MAX_ICON_DIMENSION = 128; 658 659 protected static final int MAX_ICON_DIMENSION_LOWRAM = 32; 660 661 protected static final ShortcutQuery QUERY_ALL = new ShortcutQuery(); 662 663 protected final ArrayList<String> mCallerPermissions = new ArrayList<>(); 664 665 protected final HashMap<String, LinkedHashMap<ComponentName, Integer>> mActivityMetadataResId 666 = new HashMap<>(); 667 668 protected final Map<Integer, UserInfo> mUserInfos = new HashMap<>(); 669 protected final Map<Integer, Boolean> mRunningUsers = new HashMap<>(); 670 protected final Map<Integer, Boolean> mUnlockedUsers = new HashMap<>(); 671 672 protected static final String PACKAGE_SYSTEM_LAUNCHER = "com.android.systemlauncher"; 673 protected static final String PACKAGE_SYSTEM_LAUNCHER_NAME = "systemlauncher_name"; 674 protected static final int PACKAGE_SYSTEM_LAUNCHER_PRIORITY = 0; 675 676 protected static final String PACKAGE_FALLBACK_LAUNCHER = "com.android.settings"; 677 protected static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback"; 678 protected static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999; 679 680 protected String mInjectedBuildFingerprint = "build1"; 681 682 static { 683 QUERY_ALL.setQueryFlags( 684 ShortcutQuery.FLAG_GET_ALL_KINDS); 685 } 686 687 @Override 688 protected void setUp() throws Exception { 689 super.setUp(); 690 691 mLooper = Looper.getMainLooper(); 692 mHandler = new Handler(mLooper); 693 694 mServiceContext = spy(new ServiceContext()); 695 mClientContext = new ClientContext(); 696 697 mMockPackageManager = mock(PackageManager.class); 698 mMockPackageManagerInternal = mock(PackageManagerInternal.class); 699 mMockUserManager = mock(UserManager.class); 700 mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class); 701 mMockActivityManagerInternal = mock(ActivityManagerInternal.class); 702 703 LocalServices.removeServiceForTest(PackageManagerInternal.class); 704 LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); 705 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 706 LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal); 707 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 708 LocalServices.addService(ActivityManagerInternal.class, mMockActivityManagerInternal); 709 710 // Prepare injection values. 711 712 mInjectedCurrentTimeMillis = START_TIME; 713 714 mInjectedPackages = new HashMap<>(); 715 addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1); 716 addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 2); 717 addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 3); 718 addPackage(CALLING_PACKAGE_4, CALLING_UID_4, 10); 719 addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4); 720 addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5); 721 addPackage(LAUNCHER_3, LAUNCHER_UID_3, 6); 722 addPackage(LAUNCHER_4, LAUNCHER_UID_4, 10); 723 724 // CALLING_PACKAGE_3 / LAUNCHER_3 are not backup target. 725 updatePackageInfo(CALLING_PACKAGE_3, 726 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); 727 updatePackageInfo(LAUNCHER_3, 728 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); 729 730 mUninstalledPackages = new HashSet<>(); 731 mSystemPackages = new HashSet<>(); 732 733 mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); 734 735 deleteAllSavedFiles(); 736 737 // Set up users. 738 when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( 739 inv -> mUserInfos.get((Integer) inv.getArguments()[0]))); 740 741 mUserInfos.put(USER_0, USER_INFO_0); 742 mUserInfos.put(USER_10, USER_INFO_10); 743 mUserInfos.put(USER_11, USER_INFO_11); 744 mUserInfos.put(USER_P0, USER_INFO_P0); 745 746 // Set up isUserRunning and isUserUnlocked. 747 when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( 748 inv -> b(mRunningUsers.get((Integer) inv.getArguments()[0])))); 749 750 when(mMockUserManager.isUserUnlocked(anyInt())) 751 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 752 final int userId = (Integer) inv.getArguments()[0]; 753 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId)); 754 })); 755 // isUserUnlockingOrUnlocked() return the same value as isUserUnlocked(). 756 when(mMockUserManager.isUserUnlockingOrUnlocked(anyInt())) 757 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 758 final int userId = (Integer) inv.getArguments()[0]; 759 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId)); 760 })); 761 762 when(mMockUserManager.getProfileParent(anyInt())) 763 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 764 final int userId = (Integer) inv.getArguments()[0]; 765 final UserInfo ui = mUserInfos.get(userId); 766 assertNotNull(ui); 767 if (ui.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 768 return null; 769 } 770 final UserInfo parent = mUserInfos.get(ui.profileGroupId); 771 assertNotNull(parent); 772 return parent; 773 })); 774 775 when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn( 776 ActivityManager.PROCESS_STATE_CACHED_EMPTY); 777 778 // User 0 and P0 are always running 779 mRunningUsers.put(USER_0, true); 780 mRunningUsers.put(USER_10, false); 781 mRunningUsers.put(USER_11, false); 782 mRunningUsers.put(USER_P0, true); 783 784 // Unlock all users by default. 785 mUnlockedUsers.put(USER_0, true); 786 mUnlockedUsers.put(USER_10, true); 787 mUnlockedUsers.put(USER_11, true); 788 mUnlockedUsers.put(USER_P0, true); 789 790 // Set up resources 791 setUpAppResources(); 792 793 // Start the service. 794 initService(); 795 setCaller(CALLING_PACKAGE_1); 796 797 if (ENABLE_DUMP) { 798 Log.d(TAG, "setUp done"); 799 } 800 } 801 802 private static boolean b(Boolean value) { 803 return (value != null && value); 804 } 805 806 /** 807 * Returns a boolean but also checks if the current UID is SYSTEM_UID. 808 */ 809 protected class AnswerWithSystemCheck<T> implements Answer<T> { 810 private final Function<InvocationOnMock, T> mChecker; 811 812 public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) { 813 mChecker = checker; 814 } 815 816 @Override 817 public T answer(InvocationOnMock invocation) throws Throwable { 818 assertEquals("Must be called on SYSTEM UID.", 819 Process.SYSTEM_UID, mInjectedCallingUid); 820 return mChecker.apply(invocation); 821 } 822 } 823 824 protected void setUpAppResources() throws Exception { 825 setUpAppResources(/* offset = */ 0); 826 } 827 828 protected void setUpAppResources(int ressIdOffset) throws Exception { 829 // ressIdOffset is used to adjust resource IDs to emulate the case where an updated app 830 // has resource IDs changed. 831 832 doAnswer(pmInvocation -> { 833 assertEquals(Process.SYSTEM_UID, mInjectedCallingUid); 834 835 final String packageName = (String) pmInvocation.getArguments()[0]; 836 final int userId = (Integer) pmInvocation.getArguments()[1]; 837 838 final Resources res = mock(Resources.class); 839 840 doAnswer(resInvocation -> { 841 final int argResId = (Integer) resInvocation.getArguments()[0]; 842 843 return "string-" + packageName + "-user:" + userId + "-res:" + argResId 844 + "/" + mInjectedLocale; 845 }).when(res).getString(anyInt()); 846 847 doAnswer(resInvocation -> { 848 final int resId = (Integer) resInvocation.getArguments()[0]; 849 850 // Always use the "string" resource type. The type doesn't matter during the test. 851 return packageName + ":string/r" + resId; 852 }).when(res).getResourceName(anyInt()); 853 854 doAnswer(resInvocation -> { 855 final String argResName = (String) resInvocation.getArguments()[0]; 856 final String argType = (String) resInvocation.getArguments()[1]; 857 final String argPackageName = (String) resInvocation.getArguments()[2]; 858 859 // See the above code. getResourceName() will just use "r" + res ID as the entry 860 // name. 861 String entryName = argResName; 862 if (entryName.contains("/")) { 863 entryName = ShortcutInfo.getResourceEntryName(entryName); 864 } 865 return Integer.parseInt(entryName.substring(1)) + ressIdOffset; 866 }).when(res).getIdentifier(anyString(), anyString(), anyString()); 867 return res; 868 }).when(mMockPackageManager).getResourcesForApplicationAsUser(anyString(), anyInt()); 869 } 870 871 protected static UserInfo withProfileGroupId(UserInfo in, int groupId) { 872 in.profileGroupId = groupId; 873 return in; 874 } 875 876 @Override 877 protected void tearDown() throws Exception { 878 if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown"); 879 880 shutdownServices(); 881 882 super.tearDown(); 883 } 884 885 protected Context getTestContext() { 886 return getInstrumentation().getContext(); 887 } 888 889 protected ShortcutManager getManager() { 890 return mManager; 891 } 892 893 protected void deleteAllSavedFiles() { 894 // Empty the data directory. 895 if (mInjectedFilePathRoot.exists()) { 896 Assert.assertTrue("failed to delete dir", 897 FileUtils.deleteContents(mInjectedFilePathRoot)); 898 } 899 mInjectedFilePathRoot.mkdirs(); 900 } 901 902 /** (Re-) init the manager and the service. */ 903 protected void initService() { 904 shutdownServices(); 905 906 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 907 908 // Instantiate targets. 909 mService = new ShortcutServiceTestable(mServiceContext, mLooper); 910 mManager = new ShortcutManagerTestable(mClientContext, mService); 911 912 mInternal = LocalServices.getService(ShortcutServiceInternal.class); 913 914 mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext); 915 mLauncherApps = null; 916 mLauncherAppsMap.clear(); 917 918 // Send boot sequence events. 919 mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY); 920 921 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 922 } 923 924 protected void shutdownServices() { 925 if (mService != null) { 926 // Flush all the unsaved data from the previous instance. 927 mService.saveDirtyInfo(); 928 929 // Make sure everything is consistent. 930 mService.verifyStates(); 931 } 932 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 933 934 mService = null; 935 mManager = null; 936 mInternal = null; 937 mLauncherAppImpl = null; 938 mLauncherApps = null; 939 mLauncherAppsMap.clear(); 940 } 941 942 protected void runOnHandler(Runnable r) { 943 final long token = mServiceContext.injectClearCallingIdentity(); 944 try { 945 r.run(); 946 } finally { 947 mServiceContext.injectRestoreCallingIdentity(token); 948 } 949 } 950 951 protected void addPackage(String packageName, int uid, int version) { 952 addPackage(packageName, uid, version, packageName); 953 } 954 955 protected Signature[] genSignatures(String... signatures) { 956 final Signature[] sigs = new Signature[signatures.length]; 957 for (int i = 0; i < signatures.length; i++){ 958 sigs[i] = new Signature(signatures[i].getBytes()); 959 } 960 return sigs; 961 } 962 963 protected PackageInfo genPackage(String packageName, int uid, int version, String... signatures) { 964 final PackageInfo pi = new PackageInfo(); 965 pi.packageName = packageName; 966 pi.applicationInfo = new ApplicationInfo(); 967 pi.applicationInfo.uid = uid; 968 pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED 969 | ApplicationInfo.FLAG_ALLOW_BACKUP; 970 pi.versionCode = version; 971 pi.applicationInfo.versionCode = version; 972 pi.signatures = genSignatures(signatures); 973 974 return pi; 975 } 976 977 protected void addPackage(String packageName, int uid, int version, String... signatures) { 978 mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures)); 979 } 980 981 protected void updatePackageInfo(String packageName, Consumer<PackageInfo> c) { 982 c.accept(mInjectedPackages.get(packageName)); 983 } 984 985 protected void updatePackageVersion(String packageName, int increment) { 986 updatePackageInfo(packageName, pi -> { 987 pi.versionCode += increment; 988 pi.applicationInfo.versionCode += increment; 989 }); 990 } 991 992 protected void updatePackageLastUpdateTime(String packageName, long increment) { 993 updatePackageInfo(packageName, pi -> { 994 pi.lastUpdateTime += increment; 995 }); 996 } 997 998 protected void setPackageLastUpdateTime(String packageName, long value) { 999 updatePackageInfo(packageName, pi -> { 1000 pi.lastUpdateTime = value; 1001 }); 1002 } 1003 1004 protected void uninstallPackage(int userId, String packageName) { 1005 if (ENABLE_DUMP) { 1006 Log.v(TAG, "Unnstall package " + packageName + " / " + userId); 1007 } 1008 mUninstalledPackages.add(PackageWithUser.of(userId, packageName)); 1009 } 1010 1011 protected void installPackage(int userId, String packageName) { 1012 if (ENABLE_DUMP) { 1013 Log.v(TAG, "Install package " + packageName + " / " + userId); 1014 } 1015 mUninstalledPackages.remove(PackageWithUser.of(userId, packageName)); 1016 } 1017 1018 PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId, 1019 boolean getSignatures) { 1020 final PackageInfo pi = mInjectedPackages.get(packageName); 1021 if (pi == null) return null; 1022 1023 final PackageInfo ret = new PackageInfo(); 1024 ret.packageName = pi.packageName; 1025 ret.versionCode = pi.versionCode; 1026 ret.lastUpdateTime = pi.lastUpdateTime; 1027 1028 ret.applicationInfo = new ApplicationInfo(pi.applicationInfo); 1029 ret.applicationInfo.uid = UserHandle.getUid(userId, pi.applicationInfo.uid); 1030 ret.applicationInfo.packageName = pi.packageName; 1031 1032 if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) { 1033 ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 1034 } 1035 if (mSystemPackages.contains(packageName)) { 1036 ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 1037 } 1038 1039 if (getSignatures) { 1040 ret.signatures = pi.signatures; 1041 } 1042 1043 return ret; 1044 } 1045 1046 protected void addApplicationInfo(PackageInfo pi, List<ApplicationInfo> list) { 1047 if (pi != null && pi.applicationInfo != null) { 1048 list.add(pi.applicationInfo); 1049 } 1050 } 1051 1052 protected List<ApplicationInfo> getInstalledApplications(int userId) { 1053 final ArrayList<ApplicationInfo> ret = new ArrayList<>(); 1054 1055 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret); 1056 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret); 1057 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret); 1058 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret); 1059 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret); 1060 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret); 1061 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret); 1062 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret); 1063 1064 return ret; 1065 } 1066 1067 private void addPackageInfo(PackageInfo pi, List<PackageInfo> list) { 1068 if (pi != null) { 1069 list.add(pi); 1070 } 1071 } 1072 1073 private List<PackageInfo> getInstalledPackagesWithUninstalled(int userId) { 1074 final ArrayList<PackageInfo> ret = new ArrayList<>(); 1075 1076 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret); 1077 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret); 1078 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret); 1079 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret); 1080 addPackageInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret); 1081 addPackageInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret); 1082 addPackageInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret); 1083 addPackageInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret); 1084 1085 return ret; 1086 } 1087 1088 protected void addManifestShortcutResource(ComponentName activity, int resId) { 1089 final String packageName = activity.getPackageName(); 1090 LinkedHashMap<ComponentName, Integer> map = mActivityMetadataResId.get(packageName); 1091 if (map == null) { 1092 map = new LinkedHashMap<>(); 1093 mActivityMetadataResId.put(packageName, map); 1094 } 1095 map.put(activity, resId); 1096 } 1097 1098 protected PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) { 1099 final PackageInfo ret = getInjectedPackageInfo(packageName, userId, 1100 /* getSignatures=*/ false); 1101 1102 final HashMap<ComponentName, Integer> activities = mActivityMetadataResId.get(packageName); 1103 if (activities != null) { 1104 final ArrayList<ActivityInfo> list = new ArrayList<>(); 1105 1106 for (ComponentName cn : activities.keySet()) { 1107 ActivityInfo ai = new ActivityInfo(); 1108 ai.packageName = cn.getPackageName(); 1109 ai.name = cn.getClassName(); 1110 ai.metaData = new Bundle(); 1111 ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn)); 1112 ai.applicationInfo = ret.applicationInfo; 1113 list.add(ai); 1114 } 1115 ret.activities = list.toArray(new ActivityInfo[list.size()]); 1116 } 1117 return ret; 1118 } 1119 1120 protected XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { 1121 if (!ShortcutParser.METADATA_KEY.equals(key) || activityInfo.metaData == null) { 1122 return null; 1123 } 1124 final int resId = activityInfo.metaData.getInt(key); 1125 return getTestContext().getResources().getXml(resId); 1126 } 1127 1128 /** Replace the current calling package */ 1129 protected void setCaller(String packageName, int userId) { 1130 mInjectedClientPackage = packageName; 1131 mInjectedCallingUid = 1132 Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false), 1133 "Unknown package").applicationInfo.uid; 1134 1135 // Set up LauncherApps for this caller. 1136 final Pair<Integer, String> key = Pair.create(userId, packageName); 1137 if (!mLauncherAppsMap.containsKey(key)) { 1138 mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl)); 1139 } 1140 mLauncherApps = mLauncherAppsMap.get(key); 1141 } 1142 1143 protected void setCaller(String packageName) { 1144 setCaller(packageName, UserHandle.USER_SYSTEM); 1145 } 1146 1147 protected String getCallingPackage() { 1148 return mInjectedClientPackage; 1149 } 1150 1151 /** 1152 * This controls {@link ShortcutService#hasShortcutHostPermission(String, int)}, but 1153 * not {@link ShortcutService#getDefaultLauncher(int)}. To control the later, use 1154 * {@link #setDefaultLauncher(int, ComponentName)}. 1155 */ 1156 protected void setDefaultLauncherChecker(BiPredicate<String, Integer> p) { 1157 mDefaultLauncherChecker = p; 1158 } 1159 1160 /** 1161 * Set the default launcher. This will update {@link #mDefaultLauncherChecker} set by 1162 * {@link #setDefaultLauncherChecker} too. 1163 */ 1164 protected void setDefaultLauncher(int userId, ComponentName launcherActivity) { 1165 mDefaultLauncher.put(userId, launcherActivity); 1166 1167 final BiPredicate<String, Integer> oldChecker = mDefaultLauncherChecker; 1168 mDefaultLauncherChecker = (checkPackageName, checkUserId) -> { 1169 if ((checkUserId == userId) && (launcherActivity != null)) { 1170 return launcherActivity.getPackageName().equals(checkPackageName); 1171 } 1172 return oldChecker.test(checkPackageName, checkUserId); 1173 }; 1174 } 1175 1176 protected void runWithCaller(String packageName, int userId, Runnable r) { 1177 final String previousPackage = mInjectedClientPackage; 1178 final int previousUserId = UserHandle.getUserId(mInjectedCallingUid); 1179 1180 setCaller(packageName, userId); 1181 1182 r.run(); 1183 1184 setCaller(previousPackage, previousUserId); 1185 } 1186 1187 protected void runWithSystemUid(Runnable r) { 1188 final int origUid = mInjectedCallingUid; 1189 mInjectedCallingUid = Process.SYSTEM_UID; 1190 r.run(); 1191 mInjectedCallingUid = origUid; 1192 } 1193 1194 protected void lookupAndFillInResourceNames(ShortcutInfo si) { 1195 runWithSystemUid(() -> si.lookupAndFillInResourceNames( 1196 mService.injectGetResourcesForApplicationAsUser(si.getPackage(), si.getUserId()))); 1197 } 1198 1199 protected int getCallingUserId() { 1200 return UserHandle.getUserId(mInjectedCallingUid); 1201 } 1202 1203 protected UserHandle getCallingUser() { 1204 return UserHandle.of(getCallingUserId()); 1205 } 1206 1207 /** For debugging */ 1208 protected void dumpsysOnLogcat() { 1209 dumpsysOnLogcat(""); 1210 } 1211 1212 protected void dumpsysOnLogcat(String message) { 1213 dumpsysOnLogcat(message, false); 1214 } 1215 1216 protected void dumpsysOnLogcat(String message, boolean force) { 1217 if (force || !ENABLE_DUMP) return; 1218 1219 Log.v(TAG, "Dumping ShortcutService: " + message); 1220 for (String line : dumpsys(null).split("\n")) { 1221 Log.v(TAG, line); 1222 } 1223 } 1224 1225 protected String dumpCheckin() { 1226 return dumpsys(new String[]{"--checkin"}); 1227 } 1228 1229 private String dumpsys(String[] args) { 1230 final ArrayList<String> origPermissions = new ArrayList<>(mCallerPermissions); 1231 mCallerPermissions.add(android.Manifest.permission.DUMP); 1232 try { 1233 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 1234 final PrintWriter pw = new PrintWriter(out); 1235 mService.dump(/* fd */ null, pw, args); 1236 pw.close(); 1237 1238 return out.toString(); 1239 } finally { 1240 mCallerPermissions.clear(); 1241 mCallerPermissions.addAll(origPermissions); 1242 } 1243 } 1244 1245 /** 1246 * For debugging, dump arbitrary file on logcat. 1247 */ 1248 protected void dumpFileOnLogcat(String path) { 1249 dumpFileOnLogcat(path, ""); 1250 } 1251 1252 protected void dumpFileOnLogcat(String path, String message) { 1253 if (!ENABLE_DUMP) return; 1254 1255 Log.v(TAG, "Dumping file: " + path + " " + message); 1256 final StringBuilder sb = new StringBuilder(); 1257 try (BufferedReader br = new BufferedReader(new FileReader(path))) { 1258 String line; 1259 while ((line = br.readLine()) != null) { 1260 Log.v(TAG, line); 1261 } 1262 } catch (Exception e) { 1263 Log.e(TAG, "Couldn't read file", e); 1264 fail("Exception " + e); 1265 } 1266 } 1267 1268 /** 1269 * For debugging, dump the main state file on logcat. 1270 */ 1271 protected void dumpBaseStateFile() { 1272 mService.saveDirtyInfo(); 1273 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath() 1274 + "/system/" + ShortcutService.FILENAME_BASE_STATE); 1275 } 1276 1277 /** 1278 * For debugging, dump per-user state file on logcat. 1279 */ 1280 protected void dumpUserFile(int userId) { 1281 dumpUserFile(userId, ""); 1282 } 1283 1284 protected void dumpUserFile(int userId, String message) { 1285 mService.saveDirtyInfo(); 1286 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath() 1287 + "/user-" + userId 1288 + "/" + ShortcutService.FILENAME_USER_PACKAGES, message); 1289 } 1290 1291 /** 1292 * Make a shortcut with an ID. 1293 */ 1294 protected ShortcutInfo makeShortcut(String id) { 1295 return makeShortcut( 1296 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1297 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1298 } 1299 1300 protected ShortcutInfo makeShortcutWithTitle(String id, String title) { 1301 return makeShortcut( 1302 id, title, /* activity =*/ null, /* icon =*/ null, 1303 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1304 } 1305 1306 /** 1307 * Make a shortcut with an ID and timestamp. 1308 */ 1309 protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) { 1310 final ShortcutInfo s = makeShortcut( 1311 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1312 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1313 s.setTimestamp(timestamp); 1314 return s; 1315 } 1316 1317 /** 1318 * Make a shortcut with an ID, a timestamp and an activity component 1319 */ 1320 protected ShortcutInfo makeShortcutWithTimestampWithActivity(String id, long timestamp, 1321 ComponentName activity) { 1322 final ShortcutInfo s = makeShortcut( 1323 id, "Title-" + id, activity, /* icon =*/ null, 1324 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1325 s.setTimestamp(timestamp); 1326 return s; 1327 } 1328 1329 /** 1330 * Make a shortcut with an ID and icon. 1331 */ 1332 protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) { 1333 return makeShortcut( 1334 id, "Title-" + id, /* activity =*/ null, icon, 1335 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1336 } 1337 1338 protected ShortcutInfo makePackageShortcut(String packageName, String id) { 1339 String origCaller = getCallingPackage(); 1340 1341 setCaller(packageName); 1342 ShortcutInfo s = makeShortcut( 1343 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1344 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1345 setCaller(origCaller); // restore the caller 1346 1347 return s; 1348 } 1349 1350 /** 1351 * Make multiple shortcuts with IDs. 1352 */ 1353 protected List<ShortcutInfo> makeShortcuts(String... ids) { 1354 final ArrayList<ShortcutInfo> ret = new ArrayList(); 1355 for (String id : ids) { 1356 ret.add(makeShortcut(id)); 1357 } 1358 return ret; 1359 } 1360 1361 protected ShortcutInfo.Builder makeShortcutBuilder() { 1362 return new ShortcutInfo.Builder(mClientContext); 1363 } 1364 1365 protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) { 1366 return makeShortcut( 1367 id, "Title-" + id, activity, /* icon =*/ null, 1368 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1369 } 1370 1371 protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) { 1372 return makeShortcut( 1373 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1374 intent, /* rank =*/ 0); 1375 } 1376 1377 protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity, 1378 String title) { 1379 return makeShortcut( 1380 id, title, activity, /* icon =*/ null, 1381 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1382 } 1383 1384 protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity, 1385 int rank) { 1386 return makeShortcut( 1387 id, "Title-" + id, activity, /* icon =*/ null, 1388 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank); 1389 } 1390 1391 /** 1392 * Make a shortcut with details. 1393 */ 1394 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity, 1395 Icon icon, Intent intent, int rank) { 1396 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1397 .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy")) 1398 .setShortLabel(title) 1399 .setRank(rank) 1400 .setIntent(intent); 1401 if (icon != null) { 1402 b.setIcon(icon); 1403 } 1404 if (activity != null) { 1405 b.setActivity(activity); 1406 } 1407 final ShortcutInfo s = b.build(); 1408 1409 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1410 1411 return s; 1412 } 1413 1414 protected ShortcutInfo makeShortcutWithIntents(String id, Intent... intents) { 1415 return makeShortcut( 1416 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1417 intents, /* rank =*/ 0); 1418 } 1419 1420 /** 1421 * Make a shortcut with details. 1422 */ 1423 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity, 1424 Icon icon, Intent[] intents, int rank) { 1425 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1426 .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy")) 1427 .setShortLabel(title) 1428 .setRank(rank) 1429 .setIntents(intents); 1430 if (icon != null) { 1431 b.setIcon(icon); 1432 } 1433 if (activity != null) { 1434 b.setActivity(activity); 1435 } 1436 final ShortcutInfo s = b.build(); 1437 1438 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1439 1440 return s; 1441 } 1442 1443 /** 1444 * Make a shortcut with details. 1445 */ 1446 protected ShortcutInfo makeShortcutWithExtras(String id, Intent intent, 1447 PersistableBundle extras) { 1448 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1449 .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy")) 1450 .setShortLabel("title-" + id) 1451 .setExtras(extras) 1452 .setIntent(intent); 1453 final ShortcutInfo s = b.build(); 1454 1455 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1456 1457 return s; 1458 } 1459 1460 /** 1461 * Make an intent. 1462 */ 1463 protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) { 1464 final Intent intent = new Intent(action); 1465 intent.setComponent(makeComponent(clazz)); 1466 intent.replaceExtras(makeBundle(bundleKeysAndValues)); 1467 return intent; 1468 } 1469 1470 /** 1471 * Make an component name, with the client context. 1472 */ 1473 @NonNull 1474 protected ComponentName makeComponent(Class<?> clazz) { 1475 return new ComponentName(mClientContext, clazz); 1476 } 1477 1478 @NonNull 1479 protected ShortcutInfo findById(List<ShortcutInfo> list, String id) { 1480 for (ShortcutInfo s : list) { 1481 if (s.getId().equals(id)) { 1482 return s; 1483 } 1484 } 1485 fail("Shortcut with id " + id + " not found"); 1486 return null; 1487 } 1488 1489 protected void assertSystem() { 1490 assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid); 1491 } 1492 1493 protected void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) { 1494 assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked()); 1495 assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked()); 1496 } 1497 1498 public static List<ShortcutInfo> assertAllNotHaveIcon( 1499 List<ShortcutInfo> actualShortcuts) { 1500 for (ShortcutInfo s : actualShortcuts) { 1501 assertNull("ID " + s.getId(), s.getIcon()); 1502 } 1503 return actualShortcuts; 1504 } 1505 1506 @NonNull 1507 protected List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts, 1508 int shortcutFlags) { 1509 for (ShortcutInfo s : actualShortcuts) { 1510 assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags, 1511 s.hasFlags(shortcutFlags)); 1512 } 1513 return actualShortcuts; 1514 } 1515 1516 protected ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) { 1517 return mService.getPackageShortcutForTest(packageName, shortcutId, userId); 1518 } 1519 1520 protected void assertShortcutExists(String packageName, String shortcutId, int userId) { 1521 assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null); 1522 } 1523 1524 protected void assertShortcutNotExists(String packageName, String shortcutId, int userId) { 1525 assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null); 1526 } 1527 1528 protected Intent[] launchShortcutAndGetIntentsInner(Runnable shortcutStarter, 1529 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1530 reset(mMockActivityManagerInternal); 1531 shortcutStarter.run(); 1532 1533 final ArgumentCaptor<Intent[]> intentsCaptor = ArgumentCaptor.forClass(Intent[].class); 1534 verify(mMockActivityManagerInternal).startActivitiesAsPackage( 1535 eq(packageName), 1536 eq(userId), 1537 intentsCaptor.capture(), 1538 any(Bundle.class)); 1539 return intentsCaptor.getValue(); 1540 } 1541 1542 protected Intent[] launchShortcutAndGetIntents( 1543 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1544 return launchShortcutAndGetIntentsInner( 1545 () -> { 1546 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1547 UserHandle.of(userId)); 1548 }, packageName, shortcutId, userId 1549 ); 1550 } 1551 1552 protected Intent launchShortcutAndGetIntent( 1553 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1554 final Intent[] intents = launchShortcutAndGetIntents(packageName, shortcutId, userId); 1555 assertEquals(1, intents.length); 1556 return intents[0]; 1557 } 1558 1559 protected Intent[] launchShortcutAndGetIntents_withShortcutInfo( 1560 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1561 return launchShortcutAndGetIntentsInner( 1562 () -> { 1563 mLauncherApps.startShortcut( 1564 getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null); 1565 }, packageName, shortcutId, userId 1566 ); 1567 } 1568 1569 protected Intent launchShortcutAndGetIntent_withShortcutInfo( 1570 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1571 final Intent[] intents = launchShortcutAndGetIntents_withShortcutInfo( 1572 packageName, shortcutId, userId); 1573 assertEquals(1, intents.length); 1574 return intents[0]; 1575 } 1576 1577 protected void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId, 1578 int userId) { 1579 assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId)); 1580 assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId)); 1581 } 1582 1583 protected void assertShortcutNotLaunched(@NonNull String packageName, 1584 @NonNull String shortcutId, int userId) { 1585 reset(mMockActivityManagerInternal); 1586 try { 1587 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1588 UserHandle.of(userId)); 1589 fail("ActivityNotFoundException was not thrown"); 1590 } catch (ActivityNotFoundException expected) { 1591 } 1592 // This shouldn't have been called. 1593 verify(mMockActivityManagerInternal, times(0)).startActivitiesAsPackage( 1594 anyString(), 1595 anyInt(), 1596 any(Intent[].class), 1597 any(Bundle.class)); 1598 } 1599 1600 protected void assertStartShortcutThrowsException(@NonNull String packageName, 1601 @NonNull String shortcutId, int userId, Class<?> expectedException) { 1602 Exception thrown = null; 1603 try { 1604 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1605 UserHandle.of(userId)); 1606 } catch (Exception e) { 1607 thrown = e; 1608 } 1609 assertNotNull("Exception was not thrown", thrown); 1610 assertEquals("Exception type different", expectedException, thrown.getClass()); 1611 } 1612 1613 protected void assertBitmapDirectories(int userId, String... expectedDirectories) { 1614 final Set<String> expected = hashSet(set(expectedDirectories)); 1615 1616 final Set<String> actual = new HashSet<>(); 1617 1618 final File[] files = mService.getUserBitmapFilePath(userId).listFiles(); 1619 if (files != null) { 1620 for (File child : files) { 1621 if (child.isDirectory()) { 1622 actual.add(child.getName()); 1623 } 1624 } 1625 } 1626 1627 assertEquals(expected, actual); 1628 } 1629 1630 protected void assertBitmapFiles(int userId, String packageName, String... expectedFiles) { 1631 final Set<String> expected = hashSet(set(expectedFiles)); 1632 1633 final Set<String> actual = new HashSet<>(); 1634 1635 final File[] files = new File(mService.getUserBitmapFilePath(userId), packageName) 1636 .listFiles(); 1637 if (files != null) { 1638 for (File child : files) { 1639 if (child.isFile()) { 1640 actual.add(child.getName()); 1641 } 1642 } 1643 } 1644 1645 assertEquals(expected, actual); 1646 } 1647 1648 protected String getBitmapFilename(int userId, String packageName, String shortcutId) { 1649 final ShortcutInfo si = mService.getPackageShortcutForTest(packageName, shortcutId, userId); 1650 if (si == null) { 1651 return null; 1652 } 1653 return new File(si.getBitmapPath()).getName(); 1654 } 1655 1656 /** 1657 * @return all shortcuts stored internally for the caller. This reflects the *internal* view 1658 * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would 1659 * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door" 1660 * which performs some extra checks, like {@link ShortcutPackage#onRestored}. 1661 */ 1662 protected List<ShortcutInfo> getCallerShortcuts() { 1663 final ShortcutPackage p = mService.getPackageShortcutForTest( 1664 getCallingPackage(), getCallingUserId()); 1665 return p == null ? null : p.getAllShortcutsForTest(); 1666 } 1667 1668 /** 1669 * @return all shortcuts owned by caller that are actually visible via ShortcutManager. 1670 * See also {@link #getCallerShortcuts}. 1671 */ 1672 protected List<ShortcutInfo> getCallerVisibleShortcuts() { 1673 final ArrayList<ShortcutInfo> ret = new ArrayList<>(); 1674 ret.addAll(mManager.getDynamicShortcuts()); 1675 ret.addAll(mManager.getPinnedShortcuts()); 1676 ret.addAll(mManager.getManifestShortcuts()); 1677 return ret; 1678 } 1679 1680 protected ShortcutInfo getCallerShortcut(String shortcutId) { 1681 return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId()); 1682 } 1683 1684 protected List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) { 1685 final List<ShortcutInfo>[] ret = new List[1]; 1686 runWithCaller(launcher, userId, () -> { 1687 final ShortcutQuery q = new ShortcutQuery(); 1688 q.setQueryFlags(queryFlags); 1689 ret[0] = mLauncherApps.getShortcuts(q, UserHandle.of(userId)); 1690 }); 1691 return ret[0]; 1692 } 1693 1694 protected List<ShortcutInfo> getLauncherPinnedShortcuts(String launcher, int userId) { 1695 return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED); 1696 } 1697 1698 protected ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId, 1699 int userId) { 1700 final List<ShortcutInfo> infoList = 1701 mLauncherApps.getShortcutInfo(packageName, list(shortcutId), 1702 UserHandle.of(userId)); 1703 assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size()); 1704 return infoList.get(0); 1705 } 1706 1707 protected Intent genPackageAddIntent(String packageName, int userId) { 1708 installPackage(userId, packageName); 1709 1710 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED); 1711 i.setData(Uri.parse("package:" + packageName)); 1712 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1713 return i; 1714 } 1715 1716 protected Intent genPackageDeleteIntent(String pakcageName, int userId) { 1717 uninstallPackage(userId, pakcageName); 1718 1719 Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED); 1720 i.setData(Uri.parse("package:" + pakcageName)); 1721 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1722 return i; 1723 } 1724 1725 protected Intent genPackageUpdateIntent(String pakcageName, int userId) { 1726 installPackage(userId, pakcageName); 1727 1728 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED); 1729 i.setData(Uri.parse("package:" + pakcageName)); 1730 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1731 i.putExtra(Intent.EXTRA_REPLACING, true); 1732 return i; 1733 } 1734 1735 protected Intent genPackageChangedIntent(String pakcageName, int userId) { 1736 Intent i = new Intent(Intent.ACTION_PACKAGE_CHANGED); 1737 i.setData(Uri.parse("package:" + pakcageName)); 1738 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1739 return i; 1740 } 1741 1742 protected Intent genPackageDataClear(String packageName, int userId) { 1743 Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); 1744 i.setData(Uri.parse("package:" + packageName)); 1745 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1746 return i; 1747 } 1748 1749 protected void assertExistsAndShadow(ShortcutPackageItem spi) { 1750 assertNotNull(spi); 1751 assertTrue(spi.getPackageInfo().isShadow()); 1752 } 1753 1754 protected File makeFile(File baseDirectory, String... paths) { 1755 File ret = baseDirectory; 1756 1757 for (String path : paths) { 1758 ret = new File(ret, path); 1759 } 1760 1761 return ret; 1762 } 1763 1764 protected boolean bitmapDirectoryExists(String packageName, int userId) { 1765 final File path = new File(mService.getUserBitmapFilePath(userId), packageName); 1766 return path.isDirectory(); 1767 } 1768 protected static ShortcutQuery buildQuery(long changedSince, 1769 String packageName, ComponentName componentName, 1770 /* @ShortcutQuery.QueryFlags */ int flags) { 1771 return buildQuery(changedSince, packageName, null, componentName, flags); 1772 } 1773 1774 protected static ShortcutQuery buildQuery(long changedSince, 1775 String packageName, List<String> shortcutIds, ComponentName componentName, 1776 /* @ShortcutQuery.QueryFlags */ int flags) { 1777 final ShortcutQuery q = new ShortcutQuery(); 1778 q.setChangedSince(changedSince); 1779 q.setPackage(packageName); 1780 q.setShortcutIds(shortcutIds); 1781 q.setActivity(componentName); 1782 q.setQueryFlags(flags); 1783 return q; 1784 } 1785 1786 protected static ShortcutQuery buildAllQuery(String packageName) { 1787 final ShortcutQuery q = new ShortcutQuery(); 1788 q.setPackage(packageName); 1789 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS); 1790 return q; 1791 } 1792 1793 protected static ShortcutQuery buildPinnedQuery(String packageName) { 1794 final ShortcutQuery q = new ShortcutQuery(); 1795 q.setPackage(packageName); 1796 q.setQueryFlags(ShortcutQuery.FLAG_GET_PINNED); 1797 return q; 1798 } 1799 1800 protected static ShortcutQuery buildQueryWithFlags(int queryFlags) { 1801 final ShortcutQuery q = new ShortcutQuery(); 1802 q.setQueryFlags(queryFlags); 1803 return q; 1804 } 1805 1806 protected void backupAndRestore() { 1807 int prevUid = mInjectedCallingUid; 1808 1809 mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it. 1810 1811 dumpsysOnLogcat("Before backup"); 1812 1813 final byte[] payload = mService.getBackupPayload(USER_0); 1814 if (ENABLE_DUMP) { 1815 final String xml = new String(payload); 1816 Log.v(TAG, "Backup payload:"); 1817 for (String line : xml.split("\n")) { 1818 Log.v(TAG, line); 1819 } 1820 } 1821 1822 // Before doing anything else, uninstall all packages. 1823 for (int userId : list(USER_0, USER_P0)) { 1824 for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3, 1825 LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) { 1826 uninstallPackage(userId, pkg); 1827 } 1828 } 1829 1830 shutdownServices(); 1831 1832 deleteAllSavedFiles(); 1833 1834 initService(); 1835 mService.applyRestore(payload, USER_0); 1836 1837 // handleUnlockUser will perform the gone package check, but it shouldn't remove 1838 // shadow information. 1839 mService.handleUnlockUser(USER_0); 1840 1841 dumpsysOnLogcat("After restore"); 1842 1843 mInjectedCallingUid = prevUid; 1844 } 1845 1846 protected void prepareCrossProfileDataSet() { 1847 mRunningUsers.put(USER_10, true); // this test needs user 10. 1848 1849 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1850 assertTrue(mManager.setDynamicShortcuts(list( 1851 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1852 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1853 }); 1854 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1855 assertTrue(mManager.setDynamicShortcuts(list( 1856 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1857 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1858 }); 1859 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1860 assertTrue(mManager.setDynamicShortcuts(list( 1861 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1862 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1863 }); 1864 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1865 assertTrue(mManager.setDynamicShortcuts(list())); 1866 }); 1867 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1868 assertTrue(mManager.setDynamicShortcuts(list( 1869 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1870 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1871 }); 1872 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1873 assertTrue(mManager.setDynamicShortcuts(list( 1874 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"), 1875 makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6")))); 1876 }); 1877 1878 runWithCaller(LAUNCHER_1, USER_0, () -> { 1879 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0); 1880 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0); 1881 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0); 1882 1883 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0); 1884 }); 1885 runWithCaller(LAUNCHER_2, USER_0, () -> { 1886 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0); 1887 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0); 1888 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0); 1889 1890 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0); 1891 }); 1892 1893 // Note LAUNCHER_3 has allowBackup=false. 1894 runWithCaller(LAUNCHER_3, USER_0, () -> { 1895 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0); 1896 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0); 1897 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0); 1898 1899 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0); 1900 }); 1901 runWithCaller(LAUNCHER_4, USER_0, () -> { 1902 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0); 1903 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0); 1904 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0); 1905 mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0); 1906 }); 1907 1908 // Launcher on a managed profile is referring ot user 0! 1909 runWithCaller(LAUNCHER_1, USER_P0, () -> { 1910 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0); 1911 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0); 1912 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"), 1913 HANDLE_USER_0); 1914 1915 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0); 1916 }); 1917 runWithCaller(LAUNCHER_1, USER_10, () -> { 1918 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10); 1919 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10); 1920 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"), 1921 HANDLE_USER_10); 1922 }); 1923 1924 // Then remove some dynamic shortcuts. 1925 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1926 assertTrue(mManager.setDynamicShortcuts(list( 1927 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1928 }); 1929 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1930 assertTrue(mManager.setDynamicShortcuts(list( 1931 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1932 }); 1933 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1934 assertTrue(mManager.setDynamicShortcuts(list( 1935 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1936 }); 1937 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1938 assertTrue(mManager.setDynamicShortcuts(list())); 1939 }); 1940 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1941 assertTrue(mManager.setDynamicShortcuts(list( 1942 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1943 }); 1944 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1945 assertTrue(mManager.setDynamicShortcuts(list( 1946 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3")))); 1947 }); 1948 } 1949 1950 public static List<ShortcutInfo> assertAllHaveIconResId( 1951 List<ShortcutInfo> actualShortcuts) { 1952 for (ShortcutInfo s : actualShortcuts) { 1953 assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource()); 1954 assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile()); 1955 } 1956 return actualShortcuts; 1957 } 1958 1959 public static List<ShortcutInfo> assertAllHaveIconFile( 1960 List<ShortcutInfo> actualShortcuts) { 1961 for (ShortcutInfo s : actualShortcuts) { 1962 assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource()); 1963 assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile()); 1964 } 1965 return actualShortcuts; 1966 } 1967 1968 public static List<ShortcutInfo> assertAllHaveIcon( 1969 List<ShortcutInfo> actualShortcuts) { 1970 for (ShortcutInfo s : actualShortcuts) { 1971 assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource()); 1972 } 1973 return actualShortcuts; 1974 } 1975 1976 public static List<ShortcutInfo> assertAllStringsResolved( 1977 List<ShortcutInfo> actualShortcuts) { 1978 for (ShortcutInfo s : actualShortcuts) { 1979 assertTrue("ID " + s.getId(), s.hasStringResourcesResolved()); 1980 } 1981 return actualShortcuts; 1982 } 1983 1984 public String readTestAsset(String assetPath) throws IOException { 1985 final StringBuilder sb = new StringBuilder(); 1986 try (BufferedReader br = new BufferedReader( 1987 new InputStreamReader( 1988 getTestContext().getResources().getAssets().open(assetPath)))) { 1989 String line; 1990 while ((line = br.readLine()) != null) { 1991 sb.append(line); 1992 sb.append(System.lineSeparator()); 1993 } 1994 } 1995 return sb.toString(); 1996 } 1997 1998 protected void prepareGetHomeActivitiesAsUser(ComponentName preferred, 1999 List<ResolveInfo> candidates, int userId) { 2000 doAnswer(inv -> { 2001 ((List) inv.getArguments()[0]).addAll(candidates); 2002 return preferred; 2003 }).when(mMockPackageManagerInternal).getHomeActivitiesAsUser(any(List.class), eq(userId)); 2004 } 2005 2006 protected static ComponentName cn(String packageName, String name) { 2007 return new ComponentName(packageName, name); 2008 } 2009 2010 protected static ResolveInfo ri(String packageName, String name, boolean isSystem, int priority) { 2011 final ResolveInfo ri = new ResolveInfo(); 2012 ri.activityInfo = new ActivityInfo(); 2013 ri.activityInfo.applicationInfo = new ApplicationInfo(); 2014 2015 ri.activityInfo.packageName = packageName; 2016 ri.activityInfo.name = name; 2017 if (isSystem) { 2018 ri.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 2019 } 2020 ri.priority = priority; 2021 return ri; 2022 } 2023 2024 protected static ResolveInfo getSystemLauncher() { 2025 return ri(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME, true, 2026 PACKAGE_SYSTEM_LAUNCHER_PRIORITY); 2027 } 2028 2029 protected static ResolveInfo getFallbackLauncher() { 2030 return ri(PACKAGE_FALLBACK_LAUNCHER, PACKAGE_FALLBACK_LAUNCHER_NAME, true, 2031 PACKAGE_FALLBACK_LAUNCHER_PRIORITY); 2032 } 2033} 2034