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