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