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