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