BaseShortcutManagerTest.java revision de3c16c8057b61bb3cc2e0c3d5603730f5841c51
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, int requestType) { 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 (MANAGED_PROFILE *not* set) 606 protected static final int USER_P1 = 21; // another profile of user 0 (MANAGED_PROFILE set) 607 608 protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0); 609 protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10); 610 protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11); 611 protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0); 612 protected static final UserHandle HANDLE_USER_P1 = UserHandle.of(USER_P1); 613 614 protected static final UserInfo USER_INFO_0 = withProfileGroupId( 615 new UserInfo(USER_0, "user0", 616 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 0); 617 618 protected static final UserInfo USER_INFO_10 = 619 new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED); 620 621 protected static final UserInfo USER_INFO_11 = 622 new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED); 623 624 /* 625 * Cheat: USER_P0 is a sub profile of USER_0, but it doesn't have the MANAGED_PROFILE flag set. 626 * Due to a change made to LauncherApps (b/34340531), work profile apps a no longer able 627 * to see the main profile, which would break tons of unit tests. We avoid it by not setting 628 * MANAGED_PROFILE for P0. 629 * We cover this negative case in CTS. (i.e. CTS has tests to make sure maanged profile 630 * can't access main profile's shortcuts.) 631 */ 632 protected static final UserInfo USER_INFO_P0 = withProfileGroupId( 633 new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), 0); 634 635 protected static final UserInfo USER_INFO_P1 = withProfileGroupId( 636 new UserInfo(USER_P1, "userP1", 637 UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE), 0); 638 639 protected BiPredicate<String, Integer> mDefaultLauncherChecker = 640 (callingPackage, userId) -> 641 LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage) 642 || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage); 643 644 private final Map<Integer, ComponentName> mDefaultLauncher = new ArrayMap<>(); 645 646 protected BiPredicate<ComponentName, Integer> mMainActivityChecker = 647 (activity, userId) -> true; 648 649 protected BiFunction<String, Integer, ComponentName> mMainActivityFetcher = 650 (packageName, userId) -> new ComponentName(packageName, MAIN_ACTIVITY_CLASS); 651 652 protected BiFunction<String, Integer, ComponentName> mPinConfirmActivityFetcher = 653 (packageName, userId) -> new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS); 654 655 protected BiPredicate<ComponentName, Integer> mEnabledActivityChecker 656 = (activity, userId) -> true; // all activities are enabled. 657 658 protected static final long START_TIME = 1440000000101L; 659 660 protected static final long INTERVAL = 10000; 661 662 protected static final int MAX_SHORTCUTS = 10; 663 664 protected static final int MAX_UPDATES_PER_INTERVAL = 3; 665 666 protected static final int MAX_ICON_DIMENSION = 128; 667 668 protected static final int MAX_ICON_DIMENSION_LOWRAM = 32; 669 670 protected static final ShortcutQuery QUERY_ALL = new ShortcutQuery(); 671 672 protected final ArrayList<String> mCallerPermissions = new ArrayList<>(); 673 674 protected final HashMap<String, LinkedHashMap<ComponentName, Integer>> mActivityMetadataResId 675 = new HashMap<>(); 676 677 protected final Map<Integer, UserInfo> mUserInfos = new HashMap<>(); 678 protected final Map<Integer, Boolean> mRunningUsers = new HashMap<>(); 679 protected final Map<Integer, Boolean> mUnlockedUsers = new HashMap<>(); 680 681 protected static final String PACKAGE_SYSTEM_LAUNCHER = "com.android.systemlauncher"; 682 protected static final String PACKAGE_SYSTEM_LAUNCHER_NAME = "systemlauncher_name"; 683 protected static final int PACKAGE_SYSTEM_LAUNCHER_PRIORITY = 0; 684 685 protected static final String PACKAGE_FALLBACK_LAUNCHER = "com.android.settings"; 686 protected static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback"; 687 protected static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999; 688 689 protected String mInjectedBuildFingerprint = "build1"; 690 691 static { 692 QUERY_ALL.setQueryFlags( 693 ShortcutQuery.FLAG_GET_ALL_KINDS); 694 } 695 696 @Override 697 protected void setUp() throws Exception { 698 super.setUp(); 699 700 mLooper = Looper.getMainLooper(); 701 mHandler = new Handler(mLooper); 702 703 mServiceContext = spy(new ServiceContext()); 704 mClientContext = new ClientContext(); 705 706 mMockPackageManager = mock(PackageManager.class); 707 mMockPackageManagerInternal = mock(PackageManagerInternal.class); 708 mMockUserManager = mock(UserManager.class); 709 mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class); 710 mMockActivityManagerInternal = mock(ActivityManagerInternal.class); 711 712 LocalServices.removeServiceForTest(PackageManagerInternal.class); 713 LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); 714 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 715 LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal); 716 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 717 LocalServices.addService(ActivityManagerInternal.class, mMockActivityManagerInternal); 718 719 // Prepare injection values. 720 721 mInjectedCurrentTimeMillis = START_TIME; 722 723 mInjectedPackages = new HashMap<>(); 724 addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1); 725 addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 2); 726 addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 3); 727 addPackage(CALLING_PACKAGE_4, CALLING_UID_4, 10); 728 addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4); 729 addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5); 730 addPackage(LAUNCHER_3, LAUNCHER_UID_3, 6); 731 addPackage(LAUNCHER_4, LAUNCHER_UID_4, 10); 732 733 // CALLING_PACKAGE_3 / LAUNCHER_3 are not backup target. 734 updatePackageInfo(CALLING_PACKAGE_3, 735 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); 736 updatePackageInfo(LAUNCHER_3, 737 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); 738 739 mUninstalledPackages = new HashSet<>(); 740 mSystemPackages = new HashSet<>(); 741 mEphemeralPackages = new HashSet<>(); 742 743 mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); 744 745 deleteAllSavedFiles(); 746 747 // Set up users. 748 when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( 749 inv -> mUserInfos.get((Integer) inv.getArguments()[0]))); 750 751 mUserInfos.put(USER_0, USER_INFO_0); 752 mUserInfos.put(USER_10, USER_INFO_10); 753 mUserInfos.put(USER_11, USER_INFO_11); 754 mUserInfos.put(USER_P0, USER_INFO_P0); 755 mUserInfos.put(USER_P1, USER_INFO_P1); 756 757 // Set up isUserRunning and isUserUnlocked. 758 when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( 759 inv -> b(mRunningUsers.get((Integer) inv.getArguments()[0])))); 760 761 when(mMockUserManager.isUserUnlocked(anyInt())) 762 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 763 final int userId = (Integer) inv.getArguments()[0]; 764 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId)); 765 })); 766 // isUserUnlockingOrUnlocked() return the same value as isUserUnlocked(). 767 when(mMockUserManager.isUserUnlockingOrUnlocked(anyInt())) 768 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 769 final int userId = (Integer) inv.getArguments()[0]; 770 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId)); 771 })); 772 773 when(mMockUserManager.getProfileParent(anyInt())) 774 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 775 final int userId = (Integer) inv.getArguments()[0]; 776 final UserInfo ui = mUserInfos.get(userId); 777 assertNotNull(ui); 778 if (ui.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 779 return null; 780 } 781 final UserInfo parent = mUserInfos.get(ui.profileGroupId); 782 assertNotNull(parent); 783 return parent; 784 })); 785 when(mMockUserManager.isManagedProfile(anyInt())) 786 .thenAnswer(new AnswerWithSystemCheck<>(inv -> { 787 final int userId = (Integer) inv.getArguments()[0]; 788 final UserInfo ui = mUserInfos.get(userId); 789 assertNotNull(ui); 790 return ui.isManagedProfile(); 791 })); 792 793 when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn( 794 ActivityManager.PROCESS_STATE_CACHED_EMPTY); 795 796 // User 0 and P0 are always running 797 mRunningUsers.put(USER_0, true); 798 mRunningUsers.put(USER_10, false); 799 mRunningUsers.put(USER_11, false); 800 mRunningUsers.put(USER_P0, true); 801 mRunningUsers.put(USER_P1, true); 802 803 // Unlock all users by default. 804 mUnlockedUsers.put(USER_0, true); 805 mUnlockedUsers.put(USER_10, true); 806 mUnlockedUsers.put(USER_11, true); 807 mUnlockedUsers.put(USER_P0, true); 808 mUnlockedUsers.put(USER_P1, true); 809 810 // Set up resources 811 setUpAppResources(); 812 813 // Start the service. 814 initService(); 815 setCaller(CALLING_PACKAGE_1); 816 817 if (ENABLE_DUMP) { 818 Log.d(TAG, "setUp done"); 819 } 820 } 821 822 private static boolean b(Boolean value) { 823 return (value != null && value); 824 } 825 826 /** 827 * Returns a boolean but also checks if the current UID is SYSTEM_UID. 828 */ 829 protected class AnswerWithSystemCheck<T> implements Answer<T> { 830 private final Function<InvocationOnMock, T> mChecker; 831 832 public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) { 833 mChecker = checker; 834 } 835 836 @Override 837 public T answer(InvocationOnMock invocation) throws Throwable { 838 assertEquals("Must be called on SYSTEM UID.", 839 Process.SYSTEM_UID, mInjectedCallingUid); 840 return mChecker.apply(invocation); 841 } 842 } 843 844 protected void setUpAppResources() throws Exception { 845 setUpAppResources(/* offset = */ 0); 846 } 847 848 protected void setUpAppResources(int ressIdOffset) throws Exception { 849 // ressIdOffset is used to adjust resource IDs to emulate the case where an updated app 850 // has resource IDs changed. 851 852 doAnswer(pmInvocation -> { 853 assertEquals(Process.SYSTEM_UID, mInjectedCallingUid); 854 855 final String packageName = (String) pmInvocation.getArguments()[0]; 856 final int userId = (Integer) pmInvocation.getArguments()[1]; 857 858 final Resources res = mock(Resources.class); 859 860 doAnswer(resInvocation -> { 861 final int argResId = (Integer) resInvocation.getArguments()[0]; 862 863 return "string-" + packageName + "-user:" + userId + "-res:" + argResId 864 + "/" + mInjectedLocale; 865 }).when(res).getString(anyInt()); 866 867 doAnswer(resInvocation -> { 868 final int resId = (Integer) resInvocation.getArguments()[0]; 869 870 // Always use the "string" resource type. The type doesn't matter during the test. 871 return packageName + ":string/r" + resId; 872 }).when(res).getResourceName(anyInt()); 873 874 doAnswer(resInvocation -> { 875 final String argResName = (String) resInvocation.getArguments()[0]; 876 final String argType = (String) resInvocation.getArguments()[1]; 877 final String argPackageName = (String) resInvocation.getArguments()[2]; 878 879 // See the above code. getResourceName() will just use "r" + res ID as the entry 880 // name. 881 String entryName = argResName; 882 if (entryName.contains("/")) { 883 entryName = ShortcutInfo.getResourceEntryName(entryName); 884 } 885 return Integer.parseInt(entryName.substring(1)) + ressIdOffset; 886 }).when(res).getIdentifier(anyString(), anyString(), anyString()); 887 return res; 888 }).when(mMockPackageManager).getResourcesForApplicationAsUser(anyString(), anyInt()); 889 } 890 891 protected static UserInfo withProfileGroupId(UserInfo in, int groupId) { 892 in.profileGroupId = groupId; 893 return in; 894 } 895 896 @Override 897 protected void tearDown() throws Exception { 898 if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown"); 899 900 shutdownServices(); 901 902 super.tearDown(); 903 } 904 905 protected Context getTestContext() { 906 return getInstrumentation().getContext(); 907 } 908 909 protected ShortcutManager getManager() { 910 return mManager; 911 } 912 913 protected void deleteAllSavedFiles() { 914 // Empty the data directory. 915 if (mInjectedFilePathRoot.exists()) { 916 Assert.assertTrue("failed to delete dir", 917 FileUtils.deleteContents(mInjectedFilePathRoot)); 918 } 919 mInjectedFilePathRoot.mkdirs(); 920 } 921 922 /** (Re-) init the manager and the service. */ 923 protected void initService() { 924 shutdownServices(); 925 926 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 927 928 // Instantiate targets. 929 mService = new ShortcutServiceTestable(mServiceContext, mLooper); 930 mManager = new ShortcutManagerTestable(mClientContext, mService); 931 932 mInternal = LocalServices.getService(ShortcutServiceInternal.class); 933 934 mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext); 935 mLauncherApps = null; 936 mLauncherAppsMap.clear(); 937 938 // Send boot sequence events. 939 mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY); 940 941 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 942 } 943 944 protected void shutdownServices() { 945 if (mService != null) { 946 // Flush all the unsaved data from the previous instance. 947 mService.saveDirtyInfo(); 948 949 // Make sure everything is consistent. 950 mService.verifyStates(); 951 } 952 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 953 954 mService = null; 955 mManager = null; 956 mInternal = null; 957 mLauncherAppImpl = null; 958 mLauncherApps = null; 959 mLauncherAppsMap.clear(); 960 } 961 962 protected void runOnHandler(Runnable r) { 963 final long token = mServiceContext.injectClearCallingIdentity(); 964 try { 965 r.run(); 966 } finally { 967 mServiceContext.injectRestoreCallingIdentity(token); 968 } 969 } 970 971 protected void addPackage(String packageName, int uid, int version) { 972 addPackage(packageName, uid, version, packageName); 973 } 974 975 protected Signature[] genSignatures(String... signatures) { 976 final Signature[] sigs = new Signature[signatures.length]; 977 for (int i = 0; i < signatures.length; i++){ 978 sigs[i] = new Signature(signatures[i].getBytes()); 979 } 980 return sigs; 981 } 982 983 protected PackageInfo genPackage(String packageName, int uid, int version, String... signatures) { 984 final PackageInfo pi = new PackageInfo(); 985 pi.packageName = packageName; 986 pi.applicationInfo = new ApplicationInfo(); 987 pi.applicationInfo.uid = uid; 988 pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED 989 | ApplicationInfo.FLAG_ALLOW_BACKUP; 990 pi.versionCode = version; 991 pi.applicationInfo.versionCode = version; 992 pi.signatures = genSignatures(signatures); 993 994 return pi; 995 } 996 997 protected void addPackage(String packageName, int uid, int version, String... signatures) { 998 mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures)); 999 } 1000 1001 protected void updatePackageInfo(String packageName, Consumer<PackageInfo> c) { 1002 c.accept(mInjectedPackages.get(packageName)); 1003 } 1004 1005 protected void updatePackageVersion(String packageName, int increment) { 1006 updatePackageInfo(packageName, pi -> { 1007 pi.versionCode += increment; 1008 pi.applicationInfo.versionCode += increment; 1009 }); 1010 } 1011 1012 protected void updatePackageLastUpdateTime(String packageName, long increment) { 1013 updatePackageInfo(packageName, pi -> { 1014 pi.lastUpdateTime += increment; 1015 }); 1016 } 1017 1018 protected void setPackageLastUpdateTime(String packageName, long value) { 1019 updatePackageInfo(packageName, pi -> { 1020 pi.lastUpdateTime = value; 1021 }); 1022 } 1023 1024 protected void uninstallPackage(int userId, String packageName) { 1025 if (ENABLE_DUMP) { 1026 Log.v(TAG, "Unnstall package " + packageName + " / " + userId); 1027 } 1028 mUninstalledPackages.add(PackageWithUser.of(userId, packageName)); 1029 } 1030 1031 protected void installPackage(int userId, String packageName) { 1032 if (ENABLE_DUMP) { 1033 Log.v(TAG, "Install package " + packageName + " / " + userId); 1034 } 1035 mUninstalledPackages.remove(PackageWithUser.of(userId, packageName)); 1036 } 1037 1038 PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId, 1039 boolean getSignatures) { 1040 final PackageInfo pi = mInjectedPackages.get(packageName); 1041 if (pi == null) return null; 1042 1043 final PackageInfo ret = new PackageInfo(); 1044 ret.packageName = pi.packageName; 1045 ret.versionCode = pi.versionCode; 1046 ret.lastUpdateTime = pi.lastUpdateTime; 1047 1048 ret.applicationInfo = new ApplicationInfo(pi.applicationInfo); 1049 ret.applicationInfo.uid = UserHandle.getUid(userId, pi.applicationInfo.uid); 1050 ret.applicationInfo.packageName = pi.packageName; 1051 1052 if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) { 1053 ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 1054 } 1055 if (mEphemeralPackages.contains(PackageWithUser.of(userId, packageName))) { 1056 ret.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL; 1057 } 1058 if (mSystemPackages.contains(packageName)) { 1059 ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 1060 } 1061 1062 if (getSignatures) { 1063 ret.signatures = pi.signatures; 1064 } 1065 1066 return ret; 1067 } 1068 1069 protected void addApplicationInfo(PackageInfo pi, List<ApplicationInfo> list) { 1070 if (pi != null && pi.applicationInfo != null) { 1071 list.add(pi.applicationInfo); 1072 } 1073 } 1074 1075 protected List<ApplicationInfo> getInstalledApplications(int userId) { 1076 final ArrayList<ApplicationInfo> ret = new ArrayList<>(); 1077 1078 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret); 1079 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret); 1080 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret); 1081 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret); 1082 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret); 1083 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret); 1084 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret); 1085 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret); 1086 1087 return ret; 1088 } 1089 1090 private void addPackageInfo(PackageInfo pi, List<PackageInfo> list) { 1091 if (pi != null) { 1092 list.add(pi); 1093 } 1094 } 1095 1096 private List<PackageInfo> getInstalledPackagesWithUninstalled(int userId) { 1097 final ArrayList<PackageInfo> ret = new ArrayList<>(); 1098 1099 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret); 1100 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret); 1101 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret); 1102 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret); 1103 addPackageInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret); 1104 addPackageInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret); 1105 addPackageInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret); 1106 addPackageInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret); 1107 1108 return ret; 1109 } 1110 1111 protected void addManifestShortcutResource(ComponentName activity, int resId) { 1112 final String packageName = activity.getPackageName(); 1113 LinkedHashMap<ComponentName, Integer> map = mActivityMetadataResId.get(packageName); 1114 if (map == null) { 1115 map = new LinkedHashMap<>(); 1116 mActivityMetadataResId.put(packageName, map); 1117 } 1118 map.put(activity, resId); 1119 } 1120 1121 protected PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) { 1122 final PackageInfo ret = getInjectedPackageInfo(packageName, userId, 1123 /* getSignatures=*/ false); 1124 1125 final HashMap<ComponentName, Integer> activities = mActivityMetadataResId.get(packageName); 1126 if (activities != null) { 1127 final ArrayList<ActivityInfo> list = new ArrayList<>(); 1128 1129 for (ComponentName cn : activities.keySet()) { 1130 ActivityInfo ai = new ActivityInfo(); 1131 ai.packageName = cn.getPackageName(); 1132 ai.name = cn.getClassName(); 1133 ai.metaData = new Bundle(); 1134 ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn)); 1135 ai.applicationInfo = ret.applicationInfo; 1136 list.add(ai); 1137 } 1138 ret.activities = list.toArray(new ActivityInfo[list.size()]); 1139 } 1140 return ret; 1141 } 1142 1143 protected XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { 1144 if (!ShortcutParser.METADATA_KEY.equals(key) || activityInfo.metaData == null) { 1145 return null; 1146 } 1147 final int resId = activityInfo.metaData.getInt(key); 1148 return getTestContext().getResources().getXml(resId); 1149 } 1150 1151 /** Replace the current calling package */ 1152 protected void setCaller(String packageName, int userId) { 1153 mInjectedClientPackage = packageName; 1154 mInjectedCallingUid = 1155 Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false), 1156 "Unknown package").applicationInfo.uid; 1157 1158 // Set up LauncherApps for this caller. 1159 final Pair<Integer, String> key = Pair.create(userId, packageName); 1160 if (!mLauncherAppsMap.containsKey(key)) { 1161 mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl)); 1162 } 1163 mLauncherApps = mLauncherAppsMap.get(key); 1164 } 1165 1166 protected void setCaller(String packageName) { 1167 setCaller(packageName, UserHandle.USER_SYSTEM); 1168 } 1169 1170 protected String getCallingPackage() { 1171 return mInjectedClientPackage; 1172 } 1173 1174 /** 1175 * This controls {@link ShortcutService#hasShortcutHostPermission(String, int)}, but 1176 * not {@link ShortcutService#getDefaultLauncher(int)}. To control the later, use 1177 * {@link #setDefaultLauncher(int, ComponentName)}. 1178 */ 1179 protected void setDefaultLauncherChecker(BiPredicate<String, Integer> p) { 1180 mDefaultLauncherChecker = p; 1181 } 1182 1183 /** 1184 * Set the default launcher. This will update {@link #mDefaultLauncherChecker} set by 1185 * {@link #setDefaultLauncherChecker} too. 1186 */ 1187 protected void setDefaultLauncher(int userId, ComponentName launcherActivity) { 1188 mDefaultLauncher.put(userId, launcherActivity); 1189 1190 final BiPredicate<String, Integer> oldChecker = mDefaultLauncherChecker; 1191 mDefaultLauncherChecker = (checkPackageName, checkUserId) -> { 1192 if ((checkUserId == userId) && (launcherActivity != null)) { 1193 return launcherActivity.getPackageName().equals(checkPackageName); 1194 } 1195 return oldChecker.test(checkPackageName, checkUserId); 1196 }; 1197 } 1198 1199 protected void runWithCaller(String packageName, int userId, Runnable r) { 1200 final String previousPackage = mInjectedClientPackage; 1201 final int previousUserId = UserHandle.getUserId(mInjectedCallingUid); 1202 1203 setCaller(packageName, userId); 1204 1205 r.run(); 1206 1207 setCaller(previousPackage, previousUserId); 1208 } 1209 1210 protected void runWithSystemUid(Runnable r) { 1211 final int origUid = mInjectedCallingUid; 1212 mInjectedCallingUid = Process.SYSTEM_UID; 1213 r.run(); 1214 mInjectedCallingUid = origUid; 1215 } 1216 1217 protected void lookupAndFillInResourceNames(ShortcutInfo si) { 1218 runWithSystemUid(() -> si.lookupAndFillInResourceNames( 1219 mService.injectGetResourcesForApplicationAsUser(si.getPackage(), si.getUserId()))); 1220 } 1221 1222 protected int getCallingUserId() { 1223 return UserHandle.getUserId(mInjectedCallingUid); 1224 } 1225 1226 protected UserHandle getCallingUser() { 1227 return UserHandle.of(getCallingUserId()); 1228 } 1229 1230 /** For debugging */ 1231 protected void dumpsysOnLogcat() { 1232 dumpsysOnLogcat(""); 1233 } 1234 1235 protected void dumpsysOnLogcat(String message) { 1236 dumpsysOnLogcat(message, false); 1237 } 1238 1239 protected void dumpsysOnLogcat(String message, boolean force) { 1240 if (force || !ENABLE_DUMP) return; 1241 1242 Log.v(TAG, "Dumping ShortcutService: " + message); 1243 for (String line : dumpsys(null).split("\n")) { 1244 Log.v(TAG, line); 1245 } 1246 } 1247 1248 protected String dumpCheckin() { 1249 return dumpsys(new String[]{"--checkin"}); 1250 } 1251 1252 private String dumpsys(String[] args) { 1253 final ArrayList<String> origPermissions = new ArrayList<>(mCallerPermissions); 1254 mCallerPermissions.add(android.Manifest.permission.DUMP); 1255 try { 1256 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 1257 final PrintWriter pw = new PrintWriter(out); 1258 mService.dump(/* fd */ null, pw, args); 1259 pw.close(); 1260 1261 return out.toString(); 1262 } finally { 1263 mCallerPermissions.clear(); 1264 mCallerPermissions.addAll(origPermissions); 1265 } 1266 } 1267 1268 /** 1269 * For debugging, dump arbitrary file on logcat. 1270 */ 1271 protected void dumpFileOnLogcat(String path) { 1272 dumpFileOnLogcat(path, ""); 1273 } 1274 1275 protected void dumpFileOnLogcat(String path, String message) { 1276 if (!ENABLE_DUMP) return; 1277 1278 Log.v(TAG, "Dumping file: " + path + " " + message); 1279 final StringBuilder sb = new StringBuilder(); 1280 try (BufferedReader br = new BufferedReader(new FileReader(path))) { 1281 String line; 1282 while ((line = br.readLine()) != null) { 1283 Log.v(TAG, line); 1284 } 1285 } catch (Exception e) { 1286 Log.e(TAG, "Couldn't read file", e); 1287 fail("Exception " + e); 1288 } 1289 } 1290 1291 /** 1292 * For debugging, dump the main state file on logcat. 1293 */ 1294 protected void dumpBaseStateFile() { 1295 mService.saveDirtyInfo(); 1296 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath() 1297 + "/system/" + ShortcutService.FILENAME_BASE_STATE); 1298 } 1299 1300 /** 1301 * For debugging, dump per-user state file on logcat. 1302 */ 1303 protected void dumpUserFile(int userId) { 1304 dumpUserFile(userId, ""); 1305 } 1306 1307 protected void dumpUserFile(int userId, String message) { 1308 mService.saveDirtyInfo(); 1309 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath() 1310 + "/user-" + userId 1311 + "/" + ShortcutService.FILENAME_USER_PACKAGES, message); 1312 } 1313 1314 /** 1315 * Make a shortcut with an ID only. 1316 */ 1317 protected ShortcutInfo makeShortcutIdOnly(String id) { 1318 return new ShortcutInfo.Builder(mClientContext, id).build(); 1319 } 1320 1321 /** 1322 * Make a shortcut with an ID. 1323 */ 1324 protected ShortcutInfo makeShortcut(String id) { 1325 return makeShortcut( 1326 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1327 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1328 } 1329 1330 @Deprecated // Title was renamed to short label. 1331 protected ShortcutInfo makeShortcutWithTitle(String id, String title) { 1332 return makeShortcut( 1333 id, title, /* activity =*/ null, /* icon =*/ null, 1334 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1335 } 1336 1337 protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) { 1338 return makeShortcut( 1339 id, shortLabel, /* activity =*/ null, /* icon =*/ null, 1340 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1341 } 1342 1343 /** 1344 * Make a shortcut with an ID and timestamp. 1345 */ 1346 protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) { 1347 final ShortcutInfo s = makeShortcut( 1348 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1349 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1350 s.setTimestamp(timestamp); 1351 return s; 1352 } 1353 1354 /** 1355 * Make a shortcut with an ID, a timestamp and an activity component 1356 */ 1357 protected ShortcutInfo makeShortcutWithTimestampWithActivity(String id, long timestamp, 1358 ComponentName activity) { 1359 final ShortcutInfo s = makeShortcut( 1360 id, "Title-" + id, activity, /* icon =*/ null, 1361 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1362 s.setTimestamp(timestamp); 1363 return s; 1364 } 1365 1366 /** 1367 * Make a shortcut with an ID and icon. 1368 */ 1369 protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) { 1370 return makeShortcut( 1371 id, "Title-" + id, /* activity =*/ null, icon, 1372 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1373 } 1374 1375 protected ShortcutInfo makePackageShortcut(String packageName, String id) { 1376 String origCaller = getCallingPackage(); 1377 1378 setCaller(packageName); 1379 ShortcutInfo s = makeShortcut( 1380 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1381 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1382 setCaller(origCaller); // restore the caller 1383 1384 return s; 1385 } 1386 1387 /** 1388 * Make multiple shortcuts with IDs. 1389 */ 1390 protected List<ShortcutInfo> makeShortcuts(String... ids) { 1391 final ArrayList<ShortcutInfo> ret = new ArrayList(); 1392 for (String id : ids) { 1393 ret.add(makeShortcut(id)); 1394 } 1395 return ret; 1396 } 1397 1398 protected ShortcutInfo.Builder makeShortcutBuilder() { 1399 return new ShortcutInfo.Builder(mClientContext); 1400 } 1401 1402 protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) { 1403 return makeShortcut( 1404 id, "Title-" + id, activity, /* icon =*/ null, 1405 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1406 } 1407 1408 protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) { 1409 return makeShortcut( 1410 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1411 intent, /* rank =*/ 0); 1412 } 1413 1414 protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity, 1415 String title) { 1416 return makeShortcut( 1417 id, title, activity, /* icon =*/ null, 1418 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); 1419 } 1420 1421 protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity, 1422 int rank) { 1423 return makeShortcut( 1424 id, "Title-" + id, activity, /* icon =*/ null, 1425 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank); 1426 } 1427 1428 /** 1429 * Make a shortcut with details. 1430 */ 1431 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity, 1432 Icon icon, Intent intent, int rank) { 1433 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1434 .setActivity(new ComponentName(mClientContext.getPackageName(), "main")) 1435 .setShortLabel(title) 1436 .setRank(rank) 1437 .setIntent(intent); 1438 if (icon != null) { 1439 b.setIcon(icon); 1440 } 1441 if (activity != null) { 1442 b.setActivity(activity); 1443 } 1444 final ShortcutInfo s = b.build(); 1445 1446 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1447 1448 return s; 1449 } 1450 1451 protected ShortcutInfo makeShortcutWithIntents(String id, Intent... intents) { 1452 return makeShortcut( 1453 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null, 1454 intents, /* rank =*/ 0); 1455 } 1456 1457 /** 1458 * Make a shortcut with details. 1459 */ 1460 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity, 1461 Icon icon, Intent[] intents, int rank) { 1462 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1463 .setActivity(new ComponentName(mClientContext.getPackageName(), "main")) 1464 .setShortLabel(title) 1465 .setRank(rank) 1466 .setIntents(intents); 1467 if (icon != null) { 1468 b.setIcon(icon); 1469 } 1470 if (activity != null) { 1471 b.setActivity(activity); 1472 } 1473 final ShortcutInfo s = b.build(); 1474 1475 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1476 1477 return s; 1478 } 1479 1480 /** 1481 * Make a shortcut with details. 1482 */ 1483 protected ShortcutInfo makeShortcutWithExtras(String id, Intent intent, 1484 PersistableBundle extras) { 1485 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) 1486 .setActivity(new ComponentName(mClientContext.getPackageName(), "main")) 1487 .setShortLabel("title-" + id) 1488 .setExtras(extras) 1489 .setIntent(intent); 1490 final ShortcutInfo s = b.build(); 1491 1492 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK 1493 1494 return s; 1495 } 1496 1497 /** 1498 * Make an intent. 1499 */ 1500 protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) { 1501 final Intent intent = new Intent(action); 1502 intent.setComponent(makeComponent(clazz)); 1503 intent.replaceExtras(makeBundle(bundleKeysAndValues)); 1504 return intent; 1505 } 1506 1507 /** 1508 * Make an component name, with the client context. 1509 */ 1510 @NonNull 1511 protected ComponentName makeComponent(Class<?> clazz) { 1512 return new ComponentName(mClientContext, clazz); 1513 } 1514 1515 @NonNull 1516 protected ShortcutInfo findById(List<ShortcutInfo> list, String id) { 1517 for (ShortcutInfo s : list) { 1518 if (s.getId().equals(id)) { 1519 return s; 1520 } 1521 } 1522 fail("Shortcut with id " + id + " not found"); 1523 return null; 1524 } 1525 1526 protected void assertSystem() { 1527 assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid); 1528 } 1529 1530 protected void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) { 1531 assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked()); 1532 assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked()); 1533 } 1534 1535 public static List<ShortcutInfo> assertAllNotHaveIcon( 1536 List<ShortcutInfo> actualShortcuts) { 1537 for (ShortcutInfo s : actualShortcuts) { 1538 assertNull("ID " + s.getId(), s.getIcon()); 1539 } 1540 return actualShortcuts; 1541 } 1542 1543 @NonNull 1544 protected List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts, 1545 int shortcutFlags) { 1546 for (ShortcutInfo s : actualShortcuts) { 1547 assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags, 1548 s.hasFlags(shortcutFlags)); 1549 } 1550 return actualShortcuts; 1551 } 1552 1553 protected ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) { 1554 return mService.getPackageShortcutForTest(packageName, shortcutId, userId); 1555 } 1556 1557 protected void assertShortcutExists(String packageName, String shortcutId, int userId) { 1558 assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null); 1559 } 1560 1561 protected void assertShortcutNotExists(String packageName, String shortcutId, int userId) { 1562 assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null); 1563 } 1564 1565 protected Intent[] launchShortcutAndGetIntentsInner(Runnable shortcutStarter, 1566 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1567 reset(mMockActivityManagerInternal); 1568 shortcutStarter.run(); 1569 1570 final ArgumentCaptor<Intent[]> intentsCaptor = ArgumentCaptor.forClass(Intent[].class); 1571 verify(mMockActivityManagerInternal).startActivitiesAsPackage( 1572 eq(packageName), 1573 eq(userId), 1574 intentsCaptor.capture(), 1575 any(Bundle.class)); 1576 return intentsCaptor.getValue(); 1577 } 1578 1579 protected Intent[] launchShortcutAndGetIntents( 1580 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1581 return launchShortcutAndGetIntentsInner( 1582 () -> { 1583 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1584 UserHandle.of(userId)); 1585 }, packageName, shortcutId, userId 1586 ); 1587 } 1588 1589 protected Intent launchShortcutAndGetIntent( 1590 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1591 final Intent[] intents = launchShortcutAndGetIntents(packageName, shortcutId, userId); 1592 assertEquals(1, intents.length); 1593 return intents[0]; 1594 } 1595 1596 protected Intent[] launchShortcutAndGetIntents_withShortcutInfo( 1597 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1598 return launchShortcutAndGetIntentsInner( 1599 () -> { 1600 mLauncherApps.startShortcut( 1601 getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null); 1602 }, packageName, shortcutId, userId 1603 ); 1604 } 1605 1606 protected Intent launchShortcutAndGetIntent_withShortcutInfo( 1607 @NonNull String packageName, @NonNull String shortcutId, int userId) { 1608 final Intent[] intents = launchShortcutAndGetIntents_withShortcutInfo( 1609 packageName, shortcutId, userId); 1610 assertEquals(1, intents.length); 1611 return intents[0]; 1612 } 1613 1614 protected void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId, 1615 int userId) { 1616 assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId)); 1617 assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId)); 1618 } 1619 1620 protected void assertShortcutNotLaunched(@NonNull String packageName, 1621 @NonNull String shortcutId, int userId) { 1622 reset(mMockActivityManagerInternal); 1623 try { 1624 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1625 UserHandle.of(userId)); 1626 fail("ActivityNotFoundException was not thrown"); 1627 } catch (ActivityNotFoundException expected) { 1628 } 1629 // This shouldn't have been called. 1630 verify(mMockActivityManagerInternal, times(0)).startActivitiesAsPackage( 1631 anyString(), 1632 anyInt(), 1633 any(Intent[].class), 1634 any(Bundle.class)); 1635 } 1636 1637 protected void assertStartShortcutThrowsException(@NonNull String packageName, 1638 @NonNull String shortcutId, int userId, Class<?> expectedException) { 1639 Exception thrown = null; 1640 try { 1641 mLauncherApps.startShortcut(packageName, shortcutId, null, null, 1642 UserHandle.of(userId)); 1643 } catch (Exception e) { 1644 thrown = e; 1645 } 1646 assertNotNull("Exception was not thrown", thrown); 1647 assertEquals("Exception type different", expectedException, thrown.getClass()); 1648 } 1649 1650 protected void assertBitmapDirectories(int userId, String... expectedDirectories) { 1651 final Set<String> expected = hashSet(set(expectedDirectories)); 1652 1653 final Set<String> actual = new HashSet<>(); 1654 1655 final File[] files = mService.getUserBitmapFilePath(userId).listFiles(); 1656 if (files != null) { 1657 for (File child : files) { 1658 if (child.isDirectory()) { 1659 actual.add(child.getName()); 1660 } 1661 } 1662 } 1663 1664 assertEquals(expected, actual); 1665 } 1666 1667 protected void assertBitmapFiles(int userId, String packageName, String... expectedFiles) { 1668 final Set<String> expected = hashSet(set(expectedFiles)); 1669 1670 final Set<String> actual = new HashSet<>(); 1671 1672 final File[] files = new File(mService.getUserBitmapFilePath(userId), packageName) 1673 .listFiles(); 1674 if (files != null) { 1675 for (File child : files) { 1676 if (child.isFile()) { 1677 actual.add(child.getName()); 1678 } 1679 } 1680 } 1681 1682 assertEquals(expected, actual); 1683 } 1684 1685 protected String getBitmapFilename(int userId, String packageName, String shortcutId) { 1686 final ShortcutInfo si = mService.getPackageShortcutForTest(packageName, shortcutId, userId); 1687 if (si == null) { 1688 return null; 1689 } 1690 return new File(si.getBitmapPath()).getName(); 1691 } 1692 1693 /** 1694 * @return all shortcuts stored internally for the caller. This reflects the *internal* view 1695 * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would 1696 * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door" 1697 * which performs some extra checks, like {@link ShortcutPackage#onRestored}. 1698 */ 1699 protected List<ShortcutInfo> getCallerShortcuts() { 1700 final ShortcutPackage p = mService.getPackageShortcutForTest( 1701 getCallingPackage(), getCallingUserId()); 1702 return p == null ? null : p.getAllShortcutsForTest(); 1703 } 1704 1705 /** 1706 * @return all shortcuts owned by caller that are actually visible via ShortcutManager. 1707 * See also {@link #getCallerShortcuts}. 1708 */ 1709 protected List<ShortcutInfo> getCallerVisibleShortcuts() { 1710 final ArrayList<ShortcutInfo> ret = new ArrayList<>(); 1711 ret.addAll(mManager.getDynamicShortcuts()); 1712 ret.addAll(mManager.getPinnedShortcuts()); 1713 ret.addAll(mManager.getManifestShortcuts()); 1714 return ret; 1715 } 1716 1717 protected ShortcutInfo getCallerShortcut(String shortcutId) { 1718 return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId()); 1719 } 1720 1721 protected List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) { 1722 final List<ShortcutInfo>[] ret = new List[1]; 1723 runWithCaller(launcher, userId, () -> { 1724 final ShortcutQuery q = new ShortcutQuery(); 1725 q.setQueryFlags(queryFlags); 1726 ret[0] = mLauncherApps.getShortcuts(q, UserHandle.of(userId)); 1727 }); 1728 return ret[0]; 1729 } 1730 1731 protected List<ShortcutInfo> getLauncherPinnedShortcuts(String launcher, int userId) { 1732 return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED); 1733 } 1734 1735 protected List<ShortcutInfo> getShortcutAsLauncher(int targetUserId) { 1736 final ShortcutQuery q = new ShortcutQuery(); 1737 q.setQueryFlags(ShortcutQuery.FLAG_MATCH_DYNAMIC | ShortcutQuery.FLAG_MATCH_DYNAMIC 1738 | ShortcutQuery.FLAG_MATCH_PINNED); 1739 return mLauncherApps.getShortcuts(q, UserHandle.of(targetUserId)); 1740 } 1741 1742 protected ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId, 1743 int userId) { 1744 final List<ShortcutInfo> infoList = 1745 mLauncherApps.getShortcutInfo(packageName, list(shortcutId), 1746 UserHandle.of(userId)); 1747 assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size()); 1748 return infoList.get(0); 1749 } 1750 1751 protected Intent genPackageAddIntent(String packageName, int userId) { 1752 installPackage(userId, packageName); 1753 1754 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED); 1755 i.setData(Uri.parse("package:" + packageName)); 1756 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1757 return i; 1758 } 1759 1760 protected Intent genPackageDeleteIntent(String pakcageName, int userId) { 1761 uninstallPackage(userId, pakcageName); 1762 1763 Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED); 1764 i.setData(Uri.parse("package:" + pakcageName)); 1765 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1766 return i; 1767 } 1768 1769 protected Intent genPackageUpdateIntent(String pakcageName, int userId) { 1770 installPackage(userId, pakcageName); 1771 1772 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED); 1773 i.setData(Uri.parse("package:" + pakcageName)); 1774 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1775 i.putExtra(Intent.EXTRA_REPLACING, true); 1776 return i; 1777 } 1778 1779 protected Intent genPackageChangedIntent(String pakcageName, int userId) { 1780 Intent i = new Intent(Intent.ACTION_PACKAGE_CHANGED); 1781 i.setData(Uri.parse("package:" + pakcageName)); 1782 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1783 return i; 1784 } 1785 1786 protected Intent genPackageDataClear(String packageName, int userId) { 1787 Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); 1788 i.setData(Uri.parse("package:" + packageName)); 1789 i.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1790 return i; 1791 } 1792 1793 protected void assertExistsAndShadow(ShortcutPackageItem spi) { 1794 assertNotNull(spi); 1795 assertTrue(spi.getPackageInfo().isShadow()); 1796 } 1797 1798 protected File makeFile(File baseDirectory, String... paths) { 1799 File ret = baseDirectory; 1800 1801 for (String path : paths) { 1802 ret = new File(ret, path); 1803 } 1804 1805 return ret; 1806 } 1807 1808 protected boolean bitmapDirectoryExists(String packageName, int userId) { 1809 final File path = new File(mService.getUserBitmapFilePath(userId), packageName); 1810 return path.isDirectory(); 1811 } 1812 protected static ShortcutQuery buildQuery(long changedSince, 1813 String packageName, ComponentName componentName, 1814 /* @ShortcutQuery.QueryFlags */ int flags) { 1815 return buildQuery(changedSince, packageName, null, componentName, flags); 1816 } 1817 1818 protected static ShortcutQuery buildQuery(long changedSince, 1819 String packageName, List<String> shortcutIds, ComponentName componentName, 1820 /* @ShortcutQuery.QueryFlags */ int flags) { 1821 final ShortcutQuery q = new ShortcutQuery(); 1822 q.setChangedSince(changedSince); 1823 q.setPackage(packageName); 1824 q.setShortcutIds(shortcutIds); 1825 q.setActivity(componentName); 1826 q.setQueryFlags(flags); 1827 return q; 1828 } 1829 1830 protected static ShortcutQuery buildAllQuery(String packageName) { 1831 final ShortcutQuery q = new ShortcutQuery(); 1832 q.setPackage(packageName); 1833 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS); 1834 return q; 1835 } 1836 1837 protected static ShortcutQuery buildPinnedQuery(String packageName) { 1838 final ShortcutQuery q = new ShortcutQuery(); 1839 q.setPackage(packageName); 1840 q.setQueryFlags(ShortcutQuery.FLAG_GET_PINNED); 1841 return q; 1842 } 1843 1844 protected static ShortcutQuery buildQueryWithFlags(int queryFlags) { 1845 final ShortcutQuery q = new ShortcutQuery(); 1846 q.setQueryFlags(queryFlags); 1847 return q; 1848 } 1849 1850 protected void backupAndRestore() { 1851 int prevUid = mInjectedCallingUid; 1852 1853 mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it. 1854 1855 dumpsysOnLogcat("Before backup"); 1856 1857 final byte[] payload = mService.getBackupPayload(USER_0); 1858 if (ENABLE_DUMP) { 1859 final String xml = new String(payload); 1860 Log.v(TAG, "Backup payload:"); 1861 for (String line : xml.split("\n")) { 1862 Log.v(TAG, line); 1863 } 1864 } 1865 1866 // Before doing anything else, uninstall all packages. 1867 for (int userId : list(USER_0, USER_P0)) { 1868 for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3, 1869 LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) { 1870 uninstallPackage(userId, pkg); 1871 } 1872 } 1873 1874 shutdownServices(); 1875 1876 deleteAllSavedFiles(); 1877 1878 initService(); 1879 mService.applyRestore(payload, USER_0); 1880 1881 // handleUnlockUser will perform the gone package check, but it shouldn't remove 1882 // shadow information. 1883 mService.handleUnlockUser(USER_0); 1884 1885 dumpsysOnLogcat("After restore"); 1886 1887 mInjectedCallingUid = prevUid; 1888 } 1889 1890 protected void prepareCrossProfileDataSet() { 1891 mRunningUsers.put(USER_10, true); // this test needs user 10. 1892 1893 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1894 assertTrue(mManager.setDynamicShortcuts(list( 1895 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1896 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1897 }); 1898 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1899 assertTrue(mManager.setDynamicShortcuts(list( 1900 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1901 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1902 }); 1903 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1904 assertTrue(mManager.setDynamicShortcuts(list( 1905 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1906 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1907 }); 1908 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1909 assertTrue(mManager.setDynamicShortcuts(list())); 1910 }); 1911 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1912 assertTrue(mManager.setDynamicShortcuts(list( 1913 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"), 1914 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6")))); 1915 }); 1916 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1917 assertTrue(mManager.setDynamicShortcuts(list( 1918 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"), 1919 makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6")))); 1920 }); 1921 1922 runWithCaller(LAUNCHER_1, USER_0, () -> { 1923 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0); 1924 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0); 1925 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0); 1926 1927 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0); 1928 }); 1929 runWithCaller(LAUNCHER_2, USER_0, () -> { 1930 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0); 1931 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0); 1932 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0); 1933 1934 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0); 1935 }); 1936 1937 // Note LAUNCHER_3 has allowBackup=false. 1938 runWithCaller(LAUNCHER_3, USER_0, () -> { 1939 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0); 1940 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0); 1941 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0); 1942 1943 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0); 1944 }); 1945 runWithCaller(LAUNCHER_4, USER_0, () -> { 1946 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0); 1947 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0); 1948 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0); 1949 mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0); 1950 }); 1951 1952 // Launcher on a managed profile is referring ot user 0! 1953 runWithCaller(LAUNCHER_1, USER_P0, () -> { 1954 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0); 1955 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0); 1956 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"), 1957 HANDLE_USER_0); 1958 1959 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0); 1960 }); 1961 runWithCaller(LAUNCHER_1, USER_10, () -> { 1962 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10); 1963 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10); 1964 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"), 1965 HANDLE_USER_10); 1966 }); 1967 1968 // Then remove some dynamic shortcuts. 1969 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 1970 assertTrue(mManager.setDynamicShortcuts(list( 1971 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1972 }); 1973 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { 1974 assertTrue(mManager.setDynamicShortcuts(list( 1975 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1976 }); 1977 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { 1978 assertTrue(mManager.setDynamicShortcuts(list( 1979 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1980 }); 1981 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { 1982 assertTrue(mManager.setDynamicShortcuts(list())); 1983 }); 1984 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { 1985 assertTrue(mManager.setDynamicShortcuts(list( 1986 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); 1987 }); 1988 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 1989 assertTrue(mManager.setDynamicShortcuts(list( 1990 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3")))); 1991 }); 1992 } 1993 1994 public static List<ShortcutInfo> assertAllHaveIconResId( 1995 List<ShortcutInfo> actualShortcuts) { 1996 for (ShortcutInfo s : actualShortcuts) { 1997 assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource()); 1998 assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile()); 1999 } 2000 return actualShortcuts; 2001 } 2002 2003 public static List<ShortcutInfo> assertAllHaveIconFile( 2004 List<ShortcutInfo> actualShortcuts) { 2005 for (ShortcutInfo s : actualShortcuts) { 2006 assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource()); 2007 assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile()); 2008 } 2009 return actualShortcuts; 2010 } 2011 2012 public static List<ShortcutInfo> assertAllHaveIcon( 2013 List<ShortcutInfo> actualShortcuts) { 2014 for (ShortcutInfo s : actualShortcuts) { 2015 assertTrue("ID " + s.getId() + " has no icon ", 2016 s.hasIconFile() || s.hasIconResource() || s.getIcon() != null); 2017 } 2018 return actualShortcuts; 2019 } 2020 2021 public static List<ShortcutInfo> assertAllStringsResolved( 2022 List<ShortcutInfo> actualShortcuts) { 2023 for (ShortcutInfo s : actualShortcuts) { 2024 assertTrue("ID " + s.getId(), s.hasStringResourcesResolved()); 2025 } 2026 return actualShortcuts; 2027 } 2028 2029 public String readTestAsset(String assetPath) throws IOException { 2030 final StringBuilder sb = new StringBuilder(); 2031 try (BufferedReader br = new BufferedReader( 2032 new InputStreamReader( 2033 getTestContext().getResources().getAssets().open(assetPath)))) { 2034 String line; 2035 while ((line = br.readLine()) != null) { 2036 sb.append(line); 2037 sb.append(System.lineSeparator()); 2038 } 2039 } 2040 return sb.toString(); 2041 } 2042 2043 protected void prepareGetHomeActivitiesAsUser(ComponentName preferred, 2044 List<ResolveInfo> candidates, int userId) { 2045 doAnswer(inv -> { 2046 ((List) inv.getArguments()[0]).addAll(candidates); 2047 return preferred; 2048 }).when(mMockPackageManagerInternal).getHomeActivitiesAsUser(any(List.class), eq(userId)); 2049 } 2050 2051 protected static ComponentName cn(String packageName, String name) { 2052 return new ComponentName(packageName, name); 2053 } 2054 2055 protected static ResolveInfo ri(String packageName, String name, boolean isSystem, int priority) { 2056 final ResolveInfo ri = new ResolveInfo(); 2057 ri.activityInfo = new ActivityInfo(); 2058 ri.activityInfo.applicationInfo = new ApplicationInfo(); 2059 2060 ri.activityInfo.packageName = packageName; 2061 ri.activityInfo.name = name; 2062 if (isSystem) { 2063 ri.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 2064 } 2065 ri.priority = priority; 2066 return ri; 2067 } 2068 2069 protected static ResolveInfo getSystemLauncher() { 2070 return ri(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME, true, 2071 PACKAGE_SYSTEM_LAUNCHER_PRIORITY); 2072 } 2073 2074 protected static ResolveInfo getFallbackLauncher() { 2075 return ri(PACKAGE_FALLBACK_LAUNCHER, PACKAGE_FALLBACK_LAUNCHER_NAME, true, 2076 PACKAGE_FALLBACK_LAUNCHER_PRIORITY); 2077 } 2078 2079 protected void makeCallerForeground() { 2080 try { 2081 mService.mUidObserver.onUidStateChanged( 2082 mInjectedCallingUid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 2083 } catch (RemoteException e) { 2084 e.rethrowAsRuntimeException(); 2085 } 2086 } 2087 2088 protected void makeCallerBackground() { 2089 try { 2090 mService.mUidObserver.onUidStateChanged( 2091 mInjectedCallingUid, ActivityManager.PROCESS_STATE_TOP_SLEEPING); 2092 } catch (RemoteException e) { 2093 e.rethrowAsRuntimeException(); 2094 } 2095 } 2096 2097 protected void publishManifestShortcutsAsCaller(int resId) { 2098 addManifestShortcutResource( 2099 new ComponentName(getCallingPackage(), ShortcutActivity.class.getName()), 2100 resId); 2101 updatePackageVersion(getCallingPackage(), 1); 2102 mService.mPackageMonitor.onReceive(getTestContext(), 2103 genPackageAddIntent(getCallingPackage(), getCallingUserId())); 2104 } 2105} 2106