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