• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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