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