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