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