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