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