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