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