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