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