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