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