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