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