Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2010 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 
     17 package android.app;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.UnsupportedAppUsage;
     22 import android.content.BroadcastReceiver;
     23 import android.content.ComponentName;
     24 import android.content.Context;
     25 import android.content.IIntentReceiver;
     26 import android.content.Intent;
     27 import android.content.ServiceConnection;
     28 import android.content.pm.ApplicationInfo;
     29 import android.content.pm.IPackageManager;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.PackageManager.NameNotFoundException;
     32 import android.content.pm.SharedLibraryInfo;
     33 import android.content.pm.dex.ArtManager;
     34 import android.content.pm.split.SplitDependencyLoader;
     35 import android.content.res.AssetManager;
     36 import android.content.res.CompatibilityInfo;
     37 import android.content.res.Resources;
     38 import android.os.Build;
     39 import android.os.Bundle;
     40 import android.os.FileUtils;
     41 import android.os.Handler;
     42 import android.os.IBinder;
     43 import android.os.Process;
     44 import android.os.RemoteException;
     45 import android.os.StrictMode;
     46 import android.os.SystemProperties;
     47 import android.os.Trace;
     48 import android.os.UserHandle;
     49 import android.text.TextUtils;
     50 import android.util.AndroidRuntimeException;
     51 import android.util.ArrayMap;
     52 import android.util.Log;
     53 import android.util.Slog;
     54 import android.util.SparseArray;
     55 import android.view.Display;
     56 import android.view.DisplayAdjustments;
     57 
     58 import com.android.internal.util.ArrayUtils;
     59 
     60 import dalvik.system.BaseDexClassLoader;
     61 import dalvik.system.VMRuntime;
     62 
     63 import java.io.File;
     64 import java.io.IOException;
     65 import java.io.InputStream;
     66 import java.lang.ref.WeakReference;
     67 import java.lang.reflect.InvocationTargetException;
     68 import java.lang.reflect.Method;
     69 import java.net.URL;
     70 import java.nio.file.Paths;
     71 import java.util.ArrayList;
     72 import java.util.Arrays;
     73 import java.util.Collections;
     74 import java.util.Enumeration;
     75 import java.util.LinkedHashSet;
     76 import java.util.List;
     77 import java.util.Objects;
     78 import java.util.Set;
     79 import java.util.concurrent.Executor;
     80 
     81 final class IntentReceiverLeaked extends AndroidRuntimeException {
     82     @UnsupportedAppUsage
     83     public IntentReceiverLeaked(String msg) {
     84         super(msg);
     85     }
     86 }
     87 
     88 final class ServiceConnectionLeaked extends AndroidRuntimeException {
     89     @UnsupportedAppUsage
     90     public ServiceConnectionLeaked(String msg) {
     91         super(msg);
     92     }
     93 }
     94 
     95 /**
     96  * Local state maintained about a currently loaded .apk.
     97  * @hide
     98  */
     99 public final class LoadedApk {
    100     static final String TAG = "LoadedApk";
    101     static final boolean DEBUG = false;
    102     private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths";
    103 
    104     @UnsupportedAppUsage
    105     private final ActivityThread mActivityThread;
    106     @UnsupportedAppUsage
    107     final String mPackageName;
    108     @UnsupportedAppUsage
    109     private ApplicationInfo mApplicationInfo;
    110     @UnsupportedAppUsage
    111     private String mAppDir;
    112     @UnsupportedAppUsage
    113     private String mResDir;
    114     private String[] mOverlayDirs;
    115     @UnsupportedAppUsage
    116     private String mDataDir;
    117     @UnsupportedAppUsage
    118     private String mLibDir;
    119     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    120     private File mDataDirFile;
    121     private File mDeviceProtectedDataDirFile;
    122     private File mCredentialProtectedDataDirFile;
    123     @UnsupportedAppUsage
    124     private final ClassLoader mBaseClassLoader;
    125     private ClassLoader mDefaultClassLoader;
    126     private final boolean mSecurityViolation;
    127     private final boolean mIncludeCode;
    128     private final boolean mRegisterPackage;
    129     @UnsupportedAppUsage
    130     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
    131     /** WARNING: This may change. Don't hold external references to it. */
    132     @UnsupportedAppUsage
    133     Resources mResources;
    134     @UnsupportedAppUsage
    135     private ClassLoader mClassLoader;
    136     @UnsupportedAppUsage
    137     private Application mApplication;
    138 
    139     private String[] mSplitNames;
    140     private String[] mSplitAppDirs;
    141     @UnsupportedAppUsage
    142     private String[] mSplitResDirs;
    143     private String[] mSplitClassLoaderNames;
    144 
    145     @UnsupportedAppUsage
    146     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
    147         = new ArrayMap<>();
    148     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
    149         = new ArrayMap<>();
    150     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    151     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
    152         = new ArrayMap<>();
    153     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
    154         = new ArrayMap<>();
    155     private AppComponentFactory mAppComponentFactory;
    156 
    157     Application getApplication() {
    158         return mApplication;
    159     }
    160 
    161     /**
    162      * Create information about a new .apk
    163      *
    164      * NOTE: This constructor is called with ActivityThread's lock held,
    165      * so MUST NOT call back out to the activity manager.
    166      */
    167     public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
    168             CompatibilityInfo compatInfo, ClassLoader baseLoader,
    169             boolean securityViolation, boolean includeCode, boolean registerPackage) {
    170 
    171         mActivityThread = activityThread;
    172         setApplicationInfo(aInfo);
    173         mPackageName = aInfo.packageName;
    174         mBaseClassLoader = baseLoader;
    175         mSecurityViolation = securityViolation;
    176         mIncludeCode = includeCode;
    177         mRegisterPackage = registerPackage;
    178         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    179         mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader);
    180     }
    181 
    182     private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
    183         // If we're dealing with a multi-arch application that has both
    184         // 32 and 64 bit shared libraries, we might need to choose the secondary
    185         // depending on what the current runtime's instruction set is.
    186         if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
    187             final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
    188 
    189             // Get the instruction set that the libraries of secondary Abi is supported.
    190             // In presence of a native bridge this might be different than the one secondary Abi used.
    191             String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
    192             final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
    193             secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
    194 
    195             // If the runtimeIsa is the same as the primary isa, then we do nothing.
    196             // Everything will be set up correctly because info.nativeLibraryDir will
    197             // correspond to the right ISA.
    198             if (runtimeIsa.equals(secondaryIsa)) {
    199                 final ApplicationInfo modified = new ApplicationInfo(info);
    200                 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
    201                 modified.primaryCpuAbi = modified.secondaryCpuAbi;
    202                 return modified;
    203             }
    204         }
    205 
    206         return info;
    207     }
    208 
    209     /**
    210      * Create information about the system package.
    211      * Must call {@link #installSystemApplicationInfo} later.
    212      */
    213     LoadedApk(ActivityThread activityThread) {
    214         mActivityThread = activityThread;
    215         mApplicationInfo = new ApplicationInfo();
    216         mApplicationInfo.packageName = "android";
    217         mPackageName = "android";
    218         mAppDir = null;
    219         mResDir = null;
    220         mSplitAppDirs = null;
    221         mSplitResDirs = null;
    222         mSplitClassLoaderNames = null;
    223         mOverlayDirs = null;
    224         mDataDir = null;
    225         mDataDirFile = null;
    226         mDeviceProtectedDataDirFile = null;
    227         mCredentialProtectedDataDirFile = null;
    228         mLibDir = null;
    229         mBaseClassLoader = null;
    230         mSecurityViolation = false;
    231         mIncludeCode = true;
    232         mRegisterPackage = false;
    233         mResources = Resources.getSystem();
    234         mDefaultClassLoader = ClassLoader.getSystemClassLoader();
    235         mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
    236         mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
    237                 new ApplicationInfo(mApplicationInfo));
    238     }
    239 
    240     /**
    241      * Sets application info about the system package.
    242      */
    243     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
    244         assert info.packageName.equals("android");
    245         mApplicationInfo = info;
    246         mDefaultClassLoader = classLoader;
    247         mAppComponentFactory = createAppFactory(info, mDefaultClassLoader);
    248         mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
    249                 new ApplicationInfo(mApplicationInfo));
    250     }
    251 
    252     private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
    253         if (appInfo.appComponentFactory != null && cl != null) {
    254             try {
    255                 return (AppComponentFactory)
    256                         cl.loadClass(appInfo.appComponentFactory).newInstance();
    257             } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
    258                 Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
    259             }
    260         }
    261         return AppComponentFactory.DEFAULT;
    262     }
    263 
    264     public AppComponentFactory getAppFactory() {
    265         return mAppComponentFactory;
    266     }
    267 
    268     @UnsupportedAppUsage
    269     public String getPackageName() {
    270         return mPackageName;
    271     }
    272 
    273     @UnsupportedAppUsage
    274     public ApplicationInfo getApplicationInfo() {
    275         return mApplicationInfo;
    276     }
    277 
    278     public int getTargetSdkVersion() {
    279         return mApplicationInfo.targetSdkVersion;
    280     }
    281 
    282     public boolean isSecurityViolation() {
    283         return mSecurityViolation;
    284     }
    285 
    286     @UnsupportedAppUsage
    287     public CompatibilityInfo getCompatibilityInfo() {
    288         return mDisplayAdjustments.getCompatibilityInfo();
    289     }
    290 
    291     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
    292         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    293     }
    294 
    295     /**
    296      * Gets the array of shared libraries that are listed as
    297      * used by the given package.
    298      *
    299      * @param packageName the name of the package (note: not its
    300      * file name)
    301      * @return null-ok; the array of shared libraries, each one
    302      * a fully-qualified path
    303      */
    304     private static String[] getLibrariesFor(String packageName) {
    305         ApplicationInfo ai = null;
    306         try {
    307             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
    308                     PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
    309         } catch (RemoteException e) {
    310             throw e.rethrowFromSystemServer();
    311         }
    312 
    313         if (ai == null) {
    314             return null;
    315         }
    316 
    317         return ai.sharedLibraryFiles;
    318     }
    319 
    320     /**
    321      * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered
    322      * new.
    323      * @param aInfo The new ApplicationInfo to use for this LoadedApk
    324      * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can
    325      *                 be reused.
    326      */
    327     public void updateApplicationInfo(@NonNull ApplicationInfo aInfo,
    328             @Nullable List<String> oldPaths) {
    329         setApplicationInfo(aInfo);
    330 
    331         final List<String> newPaths = new ArrayList<>();
    332         makePaths(mActivityThread, aInfo, newPaths);
    333         final List<String> addedPaths = new ArrayList<>(newPaths.size());
    334 
    335         if (oldPaths != null) {
    336             for (String path : newPaths) {
    337                 final String apkName = path.substring(path.lastIndexOf(File.separator));
    338                 boolean match = false;
    339                 for (String oldPath : oldPaths) {
    340                     final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator));
    341                     if (apkName.equals(oldApkName)) {
    342                         match = true;
    343                         break;
    344                     }
    345                 }
    346                 if (!match) {
    347                     addedPaths.add(path);
    348                 }
    349             }
    350         } else {
    351             addedPaths.addAll(newPaths);
    352         }
    353         synchronized (this) {
    354             createOrUpdateClassLoaderLocked(addedPaths);
    355             if (mResources != null) {
    356                 final String[] splitPaths;
    357                 try {
    358                     splitPaths = getSplitPaths(null);
    359                 } catch (NameNotFoundException e) {
    360                     // This should NEVER fail.
    361                     throw new AssertionError("null split not found");
    362                 }
    363 
    364                 mResources = ResourcesManager.getInstance().getResources(null, mResDir,
    365                         splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
    366                         Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
    367                         getClassLoader());
    368             }
    369         }
    370         mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader);
    371     }
    372 
    373     private void setApplicationInfo(ApplicationInfo aInfo) {
    374         final int myUid = Process.myUid();
    375         aInfo = adjustNativeLibraryPaths(aInfo);
    376         mApplicationInfo = aInfo;
    377         mAppDir = aInfo.sourceDir;
    378         mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
    379         mOverlayDirs = aInfo.resourceDirs;
    380         mDataDir = aInfo.dataDir;
    381         mLibDir = aInfo.nativeLibraryDir;
    382         mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
    383         mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
    384         mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
    385 
    386         mSplitNames = aInfo.splitNames;
    387         mSplitAppDirs = aInfo.splitSourceDirs;
    388         mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
    389         mSplitClassLoaderNames = aInfo.splitClassLoaderNames;
    390 
    391         if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
    392             mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
    393         }
    394     }
    395 
    396     public static void makePaths(ActivityThread activityThread,
    397                                  ApplicationInfo aInfo,
    398                                  List<String> outZipPaths) {
    399         makePaths(activityThread, false, aInfo, outZipPaths, null);
    400     }
    401 
    402     private static void appendSharedLibrariesLibPathsIfNeeded(
    403             List<SharedLibraryInfo> sharedLibraries, ApplicationInfo aInfo,
    404             Set<String> outSeenPaths,
    405             List<String> outLibPaths) {
    406         if (sharedLibraries == null) {
    407             return;
    408         }
    409         for (SharedLibraryInfo lib : sharedLibraries) {
    410             List<String> paths = lib.getAllCodePaths();
    411             outSeenPaths.addAll(paths);
    412             for (String path : paths) {
    413                 appendApkLibPathIfNeeded(path, aInfo, outLibPaths);
    414             }
    415             appendSharedLibrariesLibPathsIfNeeded(
    416                     lib.getDependencies(), aInfo, outSeenPaths, outLibPaths);
    417         }
    418     }
    419 
    420     public static void makePaths(ActivityThread activityThread,
    421                                  boolean isBundledApp,
    422                                  ApplicationInfo aInfo,
    423                                  List<String> outZipPaths,
    424                                  List<String> outLibPaths) {
    425         final String appDir = aInfo.sourceDir;
    426         final String libDir = aInfo.nativeLibraryDir;
    427 
    428         outZipPaths.clear();
    429         outZipPaths.add(appDir);
    430 
    431         // Do not load all available splits if the app requested isolated split loading.
    432         if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) {
    433             Collections.addAll(outZipPaths, aInfo.splitSourceDirs);
    434         }
    435 
    436         if (outLibPaths != null) {
    437             outLibPaths.clear();
    438         }
    439 
    440         /*
    441          * The following is a bit of a hack to inject
    442          * instrumentation into the system: If the app
    443          * being started matches one of the instrumentation names,
    444          * then we combine both the "instrumentation" and
    445          * "instrumented" app into the path, along with the
    446          * concatenation of both apps' shared library lists.
    447          */
    448 
    449         String[] instrumentationLibs = null;
    450         // activityThread will be null when called from the WebView zygote; just assume
    451         // no instrumentation applies in this case.
    452         if (activityThread != null) {
    453             String instrumentationPackageName = activityThread.mInstrumentationPackageName;
    454             String instrumentationAppDir = activityThread.mInstrumentationAppDir;
    455             String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
    456             String instrumentationLibDir = activityThread.mInstrumentationLibDir;
    457 
    458             String instrumentedAppDir = activityThread.mInstrumentedAppDir;
    459             String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
    460             String instrumentedLibDir = activityThread.mInstrumentedLibDir;
    461 
    462             if (appDir.equals(instrumentationAppDir)
    463                     || appDir.equals(instrumentedAppDir)) {
    464                 outZipPaths.clear();
    465                 outZipPaths.add(instrumentationAppDir);
    466 
    467                 // Only add splits if the app did not request isolated split loading.
    468                 if (!aInfo.requestsIsolatedSplitLoading()) {
    469                     if (instrumentationSplitAppDirs != null) {
    470                         Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
    471                     }
    472 
    473                     if (!instrumentationAppDir.equals(instrumentedAppDir)) {
    474                         outZipPaths.add(instrumentedAppDir);
    475                         if (instrumentedSplitAppDirs != null) {
    476                             Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
    477                         }
    478                     }
    479                 }
    480 
    481                 if (outLibPaths != null) {
    482                     outLibPaths.add(instrumentationLibDir);
    483                     if (!instrumentationLibDir.equals(instrumentedLibDir)) {
    484                         outLibPaths.add(instrumentedLibDir);
    485                     }
    486                 }
    487 
    488                 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
    489                     instrumentationLibs = getLibrariesFor(instrumentationPackageName);
    490                 }
    491             }
    492         }
    493 
    494         if (outLibPaths != null) {
    495             if (outLibPaths.isEmpty()) {
    496                 outLibPaths.add(libDir);
    497             }
    498 
    499             // Add path to libraries in apk for current abi. Do this now because more entries
    500             // will be added to zipPaths that shouldn't be part of the library path.
    501             if (aInfo.primaryCpuAbi != null) {
    502                 // Add fake libs into the library search path if we target prior to N.
    503                 if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) {
    504                     outLibPaths.add("/system/fake-libs" +
    505                         (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
    506                 }
    507                 for (String apk : outZipPaths) {
    508                     outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
    509                 }
    510             }
    511 
    512             if (isBundledApp) {
    513                 // Add path to system libraries to libPaths;
    514                 // Access to system libs should be limited
    515                 // to bundled applications; this is why updated
    516                 // system apps are not included.
    517                 outLibPaths.add(System.getProperty("java.library.path"));
    518             }
    519         }
    520 
    521         // Add the shared libraries native paths. The dex files in shared libraries will
    522         // be resolved through shared library loaders, which are setup later.
    523         Set<String> outSeenPaths = new LinkedHashSet<>();
    524         appendSharedLibrariesLibPathsIfNeeded(
    525                 aInfo.sharedLibraryInfos, aInfo, outSeenPaths, outLibPaths);
    526 
    527         // ApplicationInfo.sharedLibraryFiles is a public API, so anyone can change it.
    528         // We prepend shared libraries that the package manager hasn't seen, maintaining their
    529         // original order where possible.
    530         if (aInfo.sharedLibraryFiles != null) {
    531             int index = 0;
    532             for (String lib : aInfo.sharedLibraryFiles) {
    533                 if (!outSeenPaths.contains(lib) && !outZipPaths.contains(lib)) {
    534                     outZipPaths.add(index, lib);
    535                     index++;
    536                     appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
    537                 }
    538             }
    539         }
    540 
    541         if (instrumentationLibs != null) {
    542             for (String lib : instrumentationLibs) {
    543                 if (!outZipPaths.contains(lib)) {
    544                     outZipPaths.add(0, lib);
    545                     appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
    546                 }
    547             }
    548         }
    549     }
    550 
    551     /**
    552      * This method appends a path to the appropriate native library folder of a
    553      * library if this library is hosted in an APK. This allows support for native
    554      * shared libraries. The library API is determined based on the application
    555      * ABI.
    556      *
    557      * @param path Path to the library.
    558      * @param applicationInfo The application depending on the library.
    559      * @param outLibPaths List to which to add the native lib path if needed.
    560      */
    561     private static void appendApkLibPathIfNeeded(@NonNull String path,
    562             @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) {
    563         // Looking at the suffix is a little hacky but a safe and simple solution.
    564         // We will be revisiting code in the next release and clean this up.
    565         if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) {
    566             if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
    567                 outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi);
    568             }
    569         }
    570     }
    571 
    572     /*
    573      * All indices received by the super class should be shifted by 1 when accessing mSplitNames,
    574      * etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't
    575      * include the base APK in the list of splits.
    576      */
    577     private class SplitDependencyLoaderImpl extends SplitDependencyLoader<NameNotFoundException> {
    578         private final String[][] mCachedResourcePaths;
    579         private final ClassLoader[] mCachedClassLoaders;
    580 
    581         SplitDependencyLoaderImpl(@NonNull SparseArray<int[]> dependencies) {
    582             super(dependencies);
    583             mCachedResourcePaths = new String[mSplitNames.length + 1][];
    584             mCachedClassLoaders = new ClassLoader[mSplitNames.length + 1];
    585         }
    586 
    587         @Override
    588         protected boolean isSplitCached(int splitIdx) {
    589             return mCachedClassLoaders[splitIdx] != null;
    590         }
    591 
    592         @Override
    593         protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
    594                 int parentSplitIdx) throws NameNotFoundException {
    595             final ArrayList<String> splitPaths = new ArrayList<>();
    596             if (splitIdx == 0) {
    597                 createOrUpdateClassLoaderLocked(null);
    598                 mCachedClassLoaders[0] = mClassLoader;
    599 
    600                 // Never add the base resources here, they always get added no matter what.
    601                 for (int configSplitIdx : configSplitIndices) {
    602                     splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
    603                 }
    604                 mCachedResourcePaths[0] = splitPaths.toArray(new String[splitPaths.size()]);
    605                 return;
    606             }
    607 
    608             // Since we handled the special base case above, parentSplitIdx is always valid.
    609             final ClassLoader parent = mCachedClassLoaders[parentSplitIdx];
    610             mCachedClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader(
    611                     mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, null, parent,
    612                     mSplitClassLoaderNames[splitIdx - 1]);
    613 
    614             Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]);
    615             splitPaths.add(mSplitResDirs[splitIdx - 1]);
    616             for (int configSplitIdx : configSplitIndices) {
    617                 splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
    618             }
    619             mCachedResourcePaths[splitIdx] = splitPaths.toArray(new String[splitPaths.size()]);
    620         }
    621 
    622         private int ensureSplitLoaded(String splitName) throws NameNotFoundException {
    623             int idx = 0;
    624             if (splitName != null) {
    625                 idx = Arrays.binarySearch(mSplitNames, splitName);
    626                 if (idx < 0) {
    627                     throw new PackageManager.NameNotFoundException(
    628                             "Split name '" + splitName + "' is not installed");
    629                 }
    630                 idx += 1;
    631             }
    632             loadDependenciesForSplit(idx);
    633             return idx;
    634         }
    635 
    636         ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException {
    637             return mCachedClassLoaders[ensureSplitLoaded(splitName)];
    638         }
    639 
    640         String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException {
    641             return mCachedResourcePaths[ensureSplitLoaded(splitName)];
    642         }
    643     }
    644 
    645     private SplitDependencyLoaderImpl mSplitLoader;
    646 
    647     ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException {
    648         if (mSplitLoader == null) {
    649             return mClassLoader;
    650         }
    651         return mSplitLoader.getClassLoaderForSplit(splitName);
    652     }
    653 
    654     String[] getSplitPaths(String splitName) throws NameNotFoundException {
    655         if (mSplitLoader == null) {
    656             return mSplitResDirs;
    657         }
    658         return mSplitLoader.getSplitPathsForSplit(splitName);
    659     }
    660 
    661     /**
    662      * Create a class loader for the {@code sharedLibrary}. Shared libraries are canonicalized,
    663      * so if we already created a class loader with that shared library, we return it.
    664      *
    665      * Implementation notes: the canonicalization of shared libraries is something dex2oat
    666      * also does.
    667      */
    668     ClassLoader createSharedLibraryLoader(SharedLibraryInfo sharedLibrary,
    669             boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
    670         List<String> paths = sharedLibrary.getAllCodePaths();
    671         List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
    672                 sharedLibrary.getDependencies(), isBundledApp, librarySearchPath,
    673                 libraryPermittedPath);
    674         final String jars = (paths.size() == 1) ? paths.get(0) :
    675                 TextUtils.join(File.pathSeparator, paths);
    676 
    677         // Shared libraries get a null parent: this has the side effect of having canonicalized
    678         // shared libraries using ApplicationLoaders cache, which is the behavior we want.
    679         return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars,
    680                     mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
    681                     libraryPermittedPath, /* parent */ null,
    682                     /* classLoaderName */ null, sharedLibraries);
    683     }
    684 
    685     private List<ClassLoader> createSharedLibrariesLoaders(List<SharedLibraryInfo> sharedLibraries,
    686             boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
    687         if (sharedLibraries == null) {
    688             return null;
    689         }
    690         List<ClassLoader> loaders = new ArrayList<>();
    691         for (SharedLibraryInfo info : sharedLibraries) {
    692             loaders.add(createSharedLibraryLoader(
    693                     info, isBundledApp, librarySearchPath, libraryPermittedPath));
    694         }
    695         return loaders;
    696     }
    697 
    698     private StrictMode.ThreadPolicy allowThreadDiskReads() {
    699         if (mActivityThread == null) {
    700             // When LoadedApk is used without an ActivityThread (usually in a
    701             // zygote context), don't call into StrictMode, as it initializes
    702             // the binder subsystem, which we don't want.
    703             return null;
    704         }
    705 
    706         return StrictMode.allowThreadDiskReads();
    707     }
    708 
    709     private void setThreadPolicy(StrictMode.ThreadPolicy policy) {
    710         if (mActivityThread != null && policy != null) {
    711             StrictMode.setThreadPolicy(policy);
    712         }
    713     }
    714 
    715     private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
    716         if (mPackageName.equals("android")) {
    717             // Note: This branch is taken for system server and we don't need to setup
    718             // jit profiling support.
    719             if (mClassLoader != null) {
    720                 // nothing to update
    721                 return;
    722             }
    723 
    724             if (mBaseClassLoader != null) {
    725                 mDefaultClassLoader = mBaseClassLoader;
    726             } else {
    727                 mDefaultClassLoader = ClassLoader.getSystemClassLoader();
    728             }
    729             mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
    730             mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
    731                     new ApplicationInfo(mApplicationInfo));
    732             return;
    733         }
    734 
    735         // Avoid the binder call when the package is the current application package.
    736         // The activity manager will perform ensure that dexopt is performed before
    737         // spinning up the process. Similarly, don't call into binder when we don't
    738         // have an ActivityThread object.
    739         if (mActivityThread != null
    740                 && !Objects.equals(mPackageName, ActivityThread.currentPackageName())
    741                 && mIncludeCode) {
    742             try {
    743                 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
    744                         PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
    745             } catch (RemoteException re) {
    746                 throw re.rethrowFromSystemServer();
    747             }
    748         }
    749 
    750         if (mRegisterPackage) {
    751             try {
    752                 ActivityManager.getService().addPackageDependency(mPackageName);
    753             } catch (RemoteException e) {
    754                 throw e.rethrowFromSystemServer();
    755             }
    756         }
    757 
    758         // Lists for the elements of zip/code and native libraries.
    759         //
    760         // Both lists are usually not empty. We expect on average one APK for the zip component,
    761         // but shared libraries and splits are not uncommon. We expect at least three elements
    762         // for native libraries (app-based, system, vendor). As such, give both some breathing
    763         // space and initialize to a small value (instead of incurring growth code).
    764         final List<String> zipPaths = new ArrayList<>(10);
    765         final List<String> libPaths = new ArrayList<>(10);
    766 
    767         boolean isBundledApp = mApplicationInfo.isSystemApp()
    768                 && !mApplicationInfo.isUpdatedSystemApp();
    769 
    770         // Vendor apks are treated as bundled only when /vendor/lib is in the default search
    771         // paths. If not, they are treated as unbundled; access to system libs is limited.
    772         // Having /vendor/lib in the default search paths means that all system processes
    773         // are allowed to use any vendor library, which in turn means that system is dependent
    774         // on vendor partition. In the contrary, not having /vendor/lib in the default search
    775         // paths mean that the two partitions are separated and thus we can treat vendor apks
    776         // as unbundled.
    777         final String defaultSearchPaths = System.getProperty("java.library.path");
    778         final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
    779         if (mApplicationInfo.getCodePath() != null
    780                 && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {
    781             isBundledApp = false;
    782         }
    783 
    784         makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
    785 
    786         String libraryPermittedPath = mDataDir;
    787 
    788         if (isBundledApp) {
    789             // For bundled apps, add the base directory of the app (e.g.,
    790             // /system/app/Foo/) to the permitted paths so that it can load libraries
    791             // embedded in module apks under the directory. For now, GmsCore is relying
    792             // on this, but this isn't specific to the app. Also note that, we don't
    793             // need to do this for unbundled apps as entire /data is already set to
    794             // the permitted paths for them.
    795             libraryPermittedPath += File.pathSeparator
    796                     + Paths.get(getAppDir()).getParent().toString();
    797 
    798             // This is necessary to grant bundled apps access to
    799             // libraries located in subdirectories of /system/lib
    800             libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
    801         }
    802 
    803         final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
    804 
    805         // If we're not asked to include code, we construct a classloader that has
    806         // no code path included. We still need to set up the library search paths
    807         // and permitted path because NativeActivity relies on it (it attempts to
    808         // call System.loadLibrary() on a classloader from a LoadedApk with
    809         // mIncludeCode == false).
    810         if (!mIncludeCode) {
    811             if (mDefaultClassLoader == null) {
    812                 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
    813                 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(
    814                         "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
    815                         librarySearchPath, libraryPermittedPath, mBaseClassLoader,
    816                         null /* classLoaderName */);
    817                 setThreadPolicy(oldPolicy);
    818                 mAppComponentFactory = AppComponentFactory.DEFAULT;
    819             }
    820 
    821             if (mClassLoader == null) {
    822                 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
    823                         new ApplicationInfo(mApplicationInfo));
    824             }
    825 
    826             return;
    827         }
    828 
    829         /*
    830          * With all the combination done (if necessary, actually create the java class
    831          * loader and set up JIT profiling support if necessary.
    832          *
    833          * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
    834          */
    835         final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
    836                 TextUtils.join(File.pathSeparator, zipPaths);
    837 
    838         if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
    839                     ", JNI path: " + librarySearchPath);
    840 
    841         boolean needToSetupJitProfiles = false;
    842         if (mDefaultClassLoader == null) {
    843             // Temporarily disable logging of disk reads on the Looper thread
    844             // as this is early and necessary.
    845             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
    846 
    847             List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
    848                     mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
    849                     libraryPermittedPath);
    850 
    851             mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
    852                     zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
    853                     libraryPermittedPath, mBaseClassLoader,
    854                     mApplicationInfo.classLoaderName, sharedLibraries);
    855             mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
    856 
    857             setThreadPolicy(oldPolicy);
    858             // Setup the class loader paths for profiling.
    859             needToSetupJitProfiles = true;
    860         }
    861 
    862         if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) {
    863             // Temporarily disable logging of disk reads on the Looper thread as this is necessary
    864             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
    865             try {
    866                 ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths);
    867             } finally {
    868                 setThreadPolicy(oldPolicy);
    869             }
    870         }
    871 
    872         // /aepx/com.android.runtime/lib, /vendor/lib, /odm/lib and /product/lib
    873         // are added to the native lib search paths of the classloader.
    874         // Note that this is done AFTER the classloader is
    875         // created by ApplicationLoaders.getDefault().getClassLoader(...). The
    876         // reason is because if we have added the paths when creating the classloader
    877         // above, the paths are also added to the search path of the linker namespace
    878         // 'classloader-namespace', which will allow ALL libs in the paths to apps.
    879         // Since only the libs listed in <partition>/etc/public.libraries.txt can be
    880         // available to apps, we shouldn't add the paths then.
    881         //
    882         // However, we need to add the paths to the classloader (Java) though. This
    883         // is because when a native lib is requested via System.loadLibrary(), the
    884         // classloader first tries to find the requested lib in its own native libs
    885         // search paths. If a lib is not found in one of the paths, dlopen() is not
    886         // called at all. This can cause a problem that a vendor public native lib
    887         // is accessible when directly opened via dlopen(), but inaccesible via
    888         // System.loadLibrary(). In order to prevent the problem, we explicitly
    889         // add the paths only to the classloader, and not to the native loader
    890         // (linker namespace).
    891         List<String> extraLibPaths = new ArrayList<>(4);
    892         String abiSuffix = VMRuntime.getRuntime().is64Bit() ? "64" : "";
    893         if (!defaultSearchPaths.contains("/apex/com.android.runtime/lib")) {
    894             extraLibPaths.add("/apex/com.android.runtime/lib" + abiSuffix);
    895         }
    896         if (!defaultSearchPaths.contains("/vendor/lib")) {
    897             extraLibPaths.add("/vendor/lib" + abiSuffix);
    898         }
    899         if (!defaultSearchPaths.contains("/odm/lib")) {
    900             extraLibPaths.add("/odm/lib" + abiSuffix);
    901         }
    902         if (!defaultSearchPaths.contains("/product/lib")) {
    903             extraLibPaths.add("/product/lib" + abiSuffix);
    904         }
    905         if (!extraLibPaths.isEmpty()) {
    906             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
    907             try {
    908                 ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, extraLibPaths);
    909             } finally {
    910                 setThreadPolicy(oldPolicy);
    911             }
    912         }
    913 
    914         if (addedPaths != null && addedPaths.size() > 0) {
    915             final String add = TextUtils.join(File.pathSeparator, addedPaths);
    916             ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add);
    917             // Setup the new code paths for profiling.
    918             needToSetupJitProfiles = true;
    919         }
    920 
    921         // Setup jit profile support.
    922         //
    923         // It is ok to call this multiple times if the application gets updated with new splits.
    924         // The runtime only keeps track of unique code paths and can handle re-registration of
    925         // the same code path. There's no need to pass `addedPaths` since any new code paths
    926         // are already in `mApplicationInfo`.
    927         //
    928         // It is NOT ok to call this function from the system_server (for any of the packages it
    929         // loads code from) so we explicitly disallow it there.
    930         //
    931         // It is not ok to call this in a zygote context where mActivityThread is null.
    932         if (needToSetupJitProfiles && !ActivityThread.isSystem() && mActivityThread != null) {
    933             setupJitProfileSupport();
    934         }
    935 
    936         // Call AppComponentFactory to select/create the main class loader of this app.
    937         // Since this may call code in the app, mDefaultClassLoader must be fully set up
    938         // before invoking the factory.
    939         // Invoke with a copy of ApplicationInfo to protect against the app changing it.
    940         if (mClassLoader == null) {
    941             mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
    942                     new ApplicationInfo(mApplicationInfo));
    943         }
    944     }
    945 
    946     @UnsupportedAppUsage
    947     public ClassLoader getClassLoader() {
    948         synchronized (this) {
    949             if (mClassLoader == null) {
    950                 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
    951             }
    952             return mClassLoader;
    953         }
    954     }
    955 
    956     private void setupJitProfileSupport() {
    957         if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
    958             return;
    959         }
    960 
    961         // If we use profiles, setup the dex reporter to notify package manager
    962         // of any relevant dex loads. The idle maintenance job will use the information
    963         // reported to optimize the loaded dex files.
    964         // Note that we only need one global reporter per app.
    965         // Make sure we do this before invoking app code for the first time so that we
    966         // can capture the complete application startup.
    967         BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
    968 
    969         // Only set up profile support if the loaded apk has the same uid as the
    970         // current process.
    971         // Currently, we do not support profiling across different apps.
    972         // (e.g. application's uid might be different when the code is
    973         // loaded by another app via createApplicationContext)
    974         if (mApplicationInfo.uid != Process.myUid()) {
    975             return;
    976         }
    977 
    978         final List<String> codePaths = new ArrayList<>();
    979         if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
    980             codePaths.add(mApplicationInfo.sourceDir);
    981         }
    982         if (mApplicationInfo.splitSourceDirs != null) {
    983             Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
    984         }
    985 
    986         if (codePaths.isEmpty()) {
    987             // If there are no code paths there's no need to setup a profile file and register with
    988             // the runtime,
    989             return;
    990         }
    991 
    992         for (int i = codePaths.size() - 1; i >= 0; i--) {
    993             String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1];
    994             String profileFile = ArtManager.getCurrentProfilePath(
    995                     mPackageName, UserHandle.myUserId(), splitName);
    996             VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)});
    997         }
    998 
    999         // Register the app data directory with the reporter. It will
   1000         // help deciding whether or not a dex file is the primary apk or a
   1001         // secondary dex.
   1002         DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
   1003     }
   1004 
   1005     /**
   1006      * Setup value for Thread.getContextClassLoader(). If the
   1007      * package will not run in in a VM with other packages, we set
   1008      * the Java context ClassLoader to the
   1009      * PackageInfo.getClassLoader value. However, if this VM can
   1010      * contain multiple packages, we intead set the Java context
   1011      * ClassLoader to a proxy that will warn about the use of Java
   1012      * context ClassLoaders and then fall through to use the
   1013      * system ClassLoader.
   1014      *
   1015      * <p> Note that this is similar to but not the same as the
   1016      * android.content.Context.getClassLoader(). While both
   1017      * context class loaders are typically set to the
   1018      * PathClassLoader used to load the package archive in the
   1019      * single application per VM case, a single Android process
   1020      * may contain several Contexts executing on one thread with
   1021      * their own logical ClassLoaders while the Java context
   1022      * ClassLoader is a thread local. This is why in the case when
   1023      * we have multiple packages per VM we do not set the Java
   1024      * context ClassLoader to an arbitrary but instead warn the
   1025      * user to set their own if we detect that they are using a
   1026      * Java library that expects it to be set.
   1027      */
   1028     private void initializeJavaContextClassLoader() {
   1029         IPackageManager pm = ActivityThread.getPackageManager();
   1030         android.content.pm.PackageInfo pi;
   1031         try {
   1032             pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
   1033                     UserHandle.myUserId());
   1034         } catch (RemoteException e) {
   1035             throw e.rethrowFromSystemServer();
   1036         }
   1037         if (pi == null) {
   1038             throw new IllegalStateException("Unable to get package info for "
   1039                     + mPackageName + "; is package not installed?");
   1040         }
   1041         /*
   1042          * Two possible indications that this package could be
   1043          * sharing its virtual machine with other packages:
   1044          *
   1045          * 1.) the sharedUserId attribute is set in the manifest,
   1046          *     indicating a request to share a VM with other
   1047          *     packages with the same sharedUserId.
   1048          *
   1049          * 2.) the application element of the manifest has an
   1050          *     attribute specifying a non-default process name,
   1051          *     indicating the desire to run in another packages VM.
   1052          */
   1053         boolean sharedUserIdSet = (pi.sharedUserId != null);
   1054         boolean processNameNotDefault =
   1055             (pi.applicationInfo != null &&
   1056              !mPackageName.equals(pi.applicationInfo.processName));
   1057         boolean sharable = (sharedUserIdSet || processNameNotDefault);
   1058         ClassLoader contextClassLoader =
   1059             (sharable)
   1060             ? new WarningContextClassLoader()
   1061             : mClassLoader;
   1062         Thread.currentThread().setContextClassLoader(contextClassLoader);
   1063     }
   1064 
   1065     private static class WarningContextClassLoader extends ClassLoader {
   1066 
   1067         private static boolean warned = false;
   1068 
   1069         private void warn(String methodName) {
   1070             if (warned) {
   1071                 return;
   1072             }
   1073             warned = true;
   1074             Thread.currentThread().setContextClassLoader(getParent());
   1075             Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
   1076                   "The class loader returned by " +
   1077                   "Thread.getContextClassLoader() may fail for processes " +
   1078                   "that host multiple applications. You should explicitly " +
   1079                   "specify a context class loader. For example: " +
   1080                   "Thread.setContextClassLoader(getClass().getClassLoader());");
   1081         }
   1082 
   1083         @Override public URL getResource(String resName) {
   1084             warn("getResource");
   1085             return getParent().getResource(resName);
   1086         }
   1087 
   1088         @Override public Enumeration<URL> getResources(String resName) throws IOException {
   1089             warn("getResources");
   1090             return getParent().getResources(resName);
   1091         }
   1092 
   1093         @Override public InputStream getResourceAsStream(String resName) {
   1094             warn("getResourceAsStream");
   1095             return getParent().getResourceAsStream(resName);
   1096         }
   1097 
   1098         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
   1099             warn("loadClass");
   1100             return getParent().loadClass(className);
   1101         }
   1102 
   1103         @Override public void setClassAssertionStatus(String cname, boolean enable) {
   1104             warn("setClassAssertionStatus");
   1105             getParent().setClassAssertionStatus(cname, enable);
   1106         }
   1107 
   1108         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
   1109             warn("setPackageAssertionStatus");
   1110             getParent().setPackageAssertionStatus(pname, enable);
   1111         }
   1112 
   1113         @Override public void setDefaultAssertionStatus(boolean enable) {
   1114             warn("setDefaultAssertionStatus");
   1115             getParent().setDefaultAssertionStatus(enable);
   1116         }
   1117 
   1118         @Override public void clearAssertionStatus() {
   1119             warn("clearAssertionStatus");
   1120             getParent().clearAssertionStatus();
   1121         }
   1122     }
   1123 
   1124     @UnsupportedAppUsage
   1125     public String getAppDir() {
   1126         return mAppDir;
   1127     }
   1128 
   1129     public String getLibDir() {
   1130         return mLibDir;
   1131     }
   1132 
   1133     @UnsupportedAppUsage
   1134     public String getResDir() {
   1135         return mResDir;
   1136     }
   1137 
   1138     public String[] getSplitAppDirs() {
   1139         return mSplitAppDirs;
   1140     }
   1141 
   1142     @UnsupportedAppUsage
   1143     public String[] getSplitResDirs() {
   1144         return mSplitResDirs;
   1145     }
   1146 
   1147     @UnsupportedAppUsage
   1148     public String[] getOverlayDirs() {
   1149         return mOverlayDirs;
   1150     }
   1151 
   1152     public String getDataDir() {
   1153         return mDataDir;
   1154     }
   1155 
   1156     @UnsupportedAppUsage
   1157     public File getDataDirFile() {
   1158         return mDataDirFile;
   1159     }
   1160 
   1161     public File getDeviceProtectedDataDirFile() {
   1162         return mDeviceProtectedDataDirFile;
   1163     }
   1164 
   1165     public File getCredentialProtectedDataDirFile() {
   1166         return mCredentialProtectedDataDirFile;
   1167     }
   1168 
   1169     @UnsupportedAppUsage
   1170     public AssetManager getAssets() {
   1171         return getResources().getAssets();
   1172     }
   1173 
   1174     @UnsupportedAppUsage
   1175     public Resources getResources() {
   1176         if (mResources == null) {
   1177             final String[] splitPaths;
   1178             try {
   1179                 splitPaths = getSplitPaths(null);
   1180             } catch (NameNotFoundException e) {
   1181                 // This should never fail.
   1182                 throw new AssertionError("null split not found");
   1183             }
   1184 
   1185             mResources = ResourcesManager.getInstance().getResources(null, mResDir,
   1186                     splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
   1187                     Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
   1188                     getClassLoader());
   1189         }
   1190         return mResources;
   1191     }
   1192 
   1193     @UnsupportedAppUsage
   1194     public Application makeApplication(boolean forceDefaultAppClass,
   1195             Instrumentation instrumentation) {
   1196         if (mApplication != null) {
   1197             return mApplication;
   1198         }
   1199 
   1200         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
   1201 
   1202         Application app = null;
   1203 
   1204         String appClass = mApplicationInfo.className;
   1205         if (forceDefaultAppClass || (appClass == null)) {
   1206             appClass = "android.app.Application";
   1207         }
   1208 
   1209         try {
   1210             java.lang.ClassLoader cl = getClassLoader();
   1211             if (!mPackageName.equals("android")) {
   1212                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
   1213                         "initializeJavaContextClassLoader");
   1214                 initializeJavaContextClassLoader();
   1215                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1216             }
   1217             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
   1218             app = mActivityThread.mInstrumentation.newApplication(
   1219                     cl, appClass, appContext);
   1220             appContext.setOuterContext(app);
   1221         } catch (Exception e) {
   1222             if (!mActivityThread.mInstrumentation.onException(app, e)) {
   1223                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1224                 throw new RuntimeException(
   1225                     "Unable to instantiate application " + appClass
   1226                     + ": " + e.toString(), e);
   1227             }
   1228         }
   1229         mActivityThread.mAllApplications.add(app);
   1230         mApplication = app;
   1231 
   1232         if (instrumentation != null) {
   1233             try {
   1234                 instrumentation.callApplicationOnCreate(app);
   1235             } catch (Exception e) {
   1236                 if (!instrumentation.onException(app, e)) {
   1237                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1238                     throw new RuntimeException(
   1239                         "Unable to create application " + app.getClass().getName()
   1240                         + ": " + e.toString(), e);
   1241                 }
   1242             }
   1243         }
   1244 
   1245         // Rewrite the R 'constants' for all library apks.
   1246         SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
   1247         final int N = packageIdentifiers.size();
   1248         for (int i = 0; i < N; i++) {
   1249             final int id = packageIdentifiers.keyAt(i);
   1250             if (id == 0x01 || id == 0x7f) {
   1251                 continue;
   1252             }
   1253 
   1254             rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
   1255         }
   1256 
   1257         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1258 
   1259         return app;
   1260     }
   1261 
   1262     @UnsupportedAppUsage
   1263     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
   1264         final Class<?> rClazz;
   1265         try {
   1266             rClazz = cl.loadClass(packageName + ".R");
   1267         } catch (ClassNotFoundException e) {
   1268             // This is not necessarily an error, as some packages do not ship with resources
   1269             // (or they do not need rewriting).
   1270             Log.i(TAG, "No resource references to update in package " + packageName);
   1271             return;
   1272         }
   1273 
   1274         final Method callback;
   1275         try {
   1276             callback = rClazz.getMethod("onResourcesLoaded", int.class);
   1277         } catch (NoSuchMethodException e) {
   1278             // No rewriting to be done.
   1279             return;
   1280         }
   1281 
   1282         Throwable cause;
   1283         try {
   1284             callback.invoke(null, id);
   1285             return;
   1286         } catch (IllegalAccessException e) {
   1287             cause = e;
   1288         } catch (InvocationTargetException e) {
   1289             cause = e.getCause();
   1290         }
   1291 
   1292         throw new RuntimeException("Failed to rewrite resource references for " + packageName,
   1293                 cause);
   1294     }
   1295 
   1296     public void removeContextRegistrations(Context context,
   1297             String who, String what) {
   1298         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
   1299         synchronized (mReceivers) {
   1300             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
   1301                     mReceivers.remove(context);
   1302             if (rmap != null) {
   1303                 for (int i = 0; i < rmap.size(); i++) {
   1304                     LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
   1305                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
   1306                             what + " " + who + " has leaked IntentReceiver "
   1307                             + rd.getIntentReceiver() + " that was " +
   1308                             "originally registered here. Are you missing a " +
   1309                             "call to unregisterReceiver()?");
   1310                     leak.setStackTrace(rd.getLocation().getStackTrace());
   1311                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
   1312                     if (reportRegistrationLeaks) {
   1313                         StrictMode.onIntentReceiverLeaked(leak);
   1314                     }
   1315                     try {
   1316                         ActivityManager.getService().unregisterReceiver(
   1317                                 rd.getIIntentReceiver());
   1318                     } catch (RemoteException e) {
   1319                         throw e.rethrowFromSystemServer();
   1320                     }
   1321                 }
   1322             }
   1323             mUnregisteredReceivers.remove(context);
   1324         }
   1325 
   1326         synchronized (mServices) {
   1327             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
   1328             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
   1329                     mServices.remove(context);
   1330             if (smap != null) {
   1331                 for (int i = 0; i < smap.size(); i++) {
   1332                     LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
   1333                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
   1334                             what + " " + who + " has leaked ServiceConnection "
   1335                             + sd.getServiceConnection() + " that was originally bound here");
   1336                     leak.setStackTrace(sd.getLocation().getStackTrace());
   1337                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
   1338                     if (reportRegistrationLeaks) {
   1339                         StrictMode.onServiceConnectionLeaked(leak);
   1340                     }
   1341                     try {
   1342                         ActivityManager.getService().unbindService(
   1343                                 sd.getIServiceConnection());
   1344                     } catch (RemoteException e) {
   1345                         throw e.rethrowFromSystemServer();
   1346                     }
   1347                     sd.doForget();
   1348                 }
   1349             }
   1350             mUnboundServices.remove(context);
   1351             //Slog.i(TAG, "Service registrations: " + mServices);
   1352         }
   1353     }
   1354 
   1355     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
   1356             Context context, Handler handler,
   1357             Instrumentation instrumentation, boolean registered) {
   1358         synchronized (mReceivers) {
   1359             LoadedApk.ReceiverDispatcher rd = null;
   1360             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
   1361             if (registered) {
   1362                 map = mReceivers.get(context);
   1363                 if (map != null) {
   1364                     rd = map.get(r);
   1365                 }
   1366             }
   1367             if (rd == null) {
   1368                 rd = new ReceiverDispatcher(r, context, handler,
   1369                         instrumentation, registered);
   1370                 if (registered) {
   1371                     if (map == null) {
   1372                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
   1373                         mReceivers.put(context, map);
   1374                     }
   1375                     map.put(r, rd);
   1376                 }
   1377             } else {
   1378                 rd.validate(context, handler);
   1379             }
   1380             rd.mForgotten = false;
   1381             return rd.getIIntentReceiver();
   1382         }
   1383     }
   1384 
   1385     public IIntentReceiver forgetReceiverDispatcher(Context context,
   1386             BroadcastReceiver r) {
   1387         synchronized (mReceivers) {
   1388             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
   1389             LoadedApk.ReceiverDispatcher rd = null;
   1390             if (map != null) {
   1391                 rd = map.get(r);
   1392                 if (rd != null) {
   1393                     map.remove(r);
   1394                     if (map.size() == 0) {
   1395                         mReceivers.remove(context);
   1396                     }
   1397                     if (r.getDebugUnregister()) {
   1398                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
   1399                                 = mUnregisteredReceivers.get(context);
   1400                         if (holder == null) {
   1401                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
   1402                             mUnregisteredReceivers.put(context, holder);
   1403                         }
   1404                         RuntimeException ex = new IllegalArgumentException(
   1405                                 "Originally unregistered here:");
   1406                         ex.fillInStackTrace();
   1407                         rd.setUnregisterLocation(ex);
   1408                         holder.put(r, rd);
   1409                     }
   1410                     rd.mForgotten = true;
   1411                     return rd.getIIntentReceiver();
   1412                 }
   1413             }
   1414             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
   1415                     = mUnregisteredReceivers.get(context);
   1416             if (holder != null) {
   1417                 rd = holder.get(r);
   1418                 if (rd != null) {
   1419                     RuntimeException ex = rd.getUnregisterLocation();
   1420                     throw new IllegalArgumentException(
   1421                             "Unregistering Receiver " + r
   1422                             + " that was already unregistered", ex);
   1423                 }
   1424             }
   1425             if (context == null) {
   1426                 throw new IllegalStateException("Unbinding Receiver " + r
   1427                         + " from Context that is no longer in use: " + context);
   1428             } else {
   1429                 throw new IllegalArgumentException("Receiver not registered: " + r);
   1430             }
   1431 
   1432         }
   1433     }
   1434 
   1435     static final class ReceiverDispatcher {
   1436 
   1437         final static class InnerReceiver extends IIntentReceiver.Stub {
   1438             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
   1439             final LoadedApk.ReceiverDispatcher mStrongRef;
   1440 
   1441             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
   1442                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
   1443                 mStrongRef = strong ? rd : null;
   1444             }
   1445 
   1446             @Override
   1447             public void performReceive(Intent intent, int resultCode, String data,
   1448                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
   1449                 final LoadedApk.ReceiverDispatcher rd;
   1450                 if (intent == null) {
   1451                     Log.wtf(TAG, "Null intent received");
   1452                     rd = null;
   1453                 } else {
   1454                     rd = mDispatcher.get();
   1455                 }
   1456                 if (ActivityThread.DEBUG_BROADCAST) {
   1457                     int seq = intent.getIntExtra("seq", -1);
   1458                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
   1459                             + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
   1460                 }
   1461                 if (rd != null) {
   1462                     rd.performReceive(intent, resultCode, data, extras,
   1463                             ordered, sticky, sendingUser);
   1464                 } else {
   1465                     // The activity manager dispatched a broadcast to a registered
   1466                     // receiver in this process, but before it could be delivered the
   1467                     // receiver was unregistered.  Acknowledge the broadcast on its
   1468                     // behalf so that the system's broadcast sequence can continue.
   1469                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
   1470                             "Finishing broadcast to unregistered receiver");
   1471                     IActivityManager mgr = ActivityManager.getService();
   1472                     try {
   1473                         if (extras != null) {
   1474                             extras.setAllowFds(false);
   1475                         }
   1476                         mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
   1477                     } catch (RemoteException e) {
   1478                         throw e.rethrowFromSystemServer();
   1479                     }
   1480                 }
   1481             }
   1482         }
   1483 
   1484         final IIntentReceiver.Stub mIIntentReceiver;
   1485         @UnsupportedAppUsage
   1486         final BroadcastReceiver mReceiver;
   1487         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   1488         final Context mContext;
   1489         final Handler mActivityThread;
   1490         final Instrumentation mInstrumentation;
   1491         final boolean mRegistered;
   1492         final IntentReceiverLeaked mLocation;
   1493         RuntimeException mUnregisterLocation;
   1494         boolean mForgotten;
   1495 
   1496         final class Args extends BroadcastReceiver.PendingResult {
   1497             private Intent mCurIntent;
   1498             private final boolean mOrdered;
   1499             private boolean mDispatched;
   1500             private boolean mRunCalled;
   1501 
   1502             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
   1503                     boolean ordered, boolean sticky, int sendingUser) {
   1504                 super(resultCode, resultData, resultExtras,
   1505                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
   1506                         sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
   1507                 mCurIntent = intent;
   1508                 mOrdered = ordered;
   1509             }
   1510 
   1511             public final Runnable getRunnable() {
   1512                 return () -> {
   1513                     final BroadcastReceiver receiver = mReceiver;
   1514                     final boolean ordered = mOrdered;
   1515 
   1516                     if (ActivityThread.DEBUG_BROADCAST) {
   1517                         int seq = mCurIntent.getIntExtra("seq", -1);
   1518                         Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
   1519                                 + " seq=" + seq + " to " + mReceiver);
   1520                         Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
   1521                                 + " mOrderedHint=" + ordered);
   1522                     }
   1523 
   1524                     final IActivityManager mgr = ActivityManager.getService();
   1525                     final Intent intent = mCurIntent;
   1526                     if (intent == null) {
   1527                         Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
   1528                                 + (mRunCalled ? ", run() has already been called" : ""));
   1529                     }
   1530 
   1531                     mCurIntent = null;
   1532                     mDispatched = true;
   1533                     mRunCalled = true;
   1534                     if (receiver == null || intent == null || mForgotten) {
   1535                         if (mRegistered && ordered) {
   1536                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
   1537                                     "Finishing null broadcast to " + mReceiver);
   1538                             sendFinished(mgr);
   1539                         }
   1540                         return;
   1541                     }
   1542 
   1543                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
   1544                     try {
   1545                         ClassLoader cl = mReceiver.getClass().getClassLoader();
   1546                         intent.setExtrasClassLoader(cl);
   1547                         intent.prepareToEnterProcess();
   1548                         setExtrasClassLoader(cl);
   1549                         receiver.setPendingResult(this);
   1550                         receiver.onReceive(mContext, intent);
   1551                     } catch (Exception e) {
   1552                         if (mRegistered && ordered) {
   1553                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
   1554                                     "Finishing failed broadcast to " + mReceiver);
   1555                             sendFinished(mgr);
   1556                         }
   1557                         if (mInstrumentation == null ||
   1558                                 !mInstrumentation.onException(mReceiver, e)) {
   1559                             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1560                             throw new RuntimeException(
   1561                                     "Error receiving broadcast " + intent
   1562                                             + " in " + mReceiver, e);
   1563                         }
   1564                     }
   1565 
   1566                     if (receiver.getPendingResult() != null) {
   1567                         finish();
   1568                     }
   1569                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   1570                 };
   1571             }
   1572         }
   1573 
   1574         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
   1575                 Handler activityThread, Instrumentation instrumentation,
   1576                 boolean registered) {
   1577             if (activityThread == null) {
   1578                 throw new NullPointerException("Handler must not be null");
   1579             }
   1580 
   1581             mIIntentReceiver = new InnerReceiver(this, !registered);
   1582             mReceiver = receiver;
   1583             mContext = context;
   1584             mActivityThread = activityThread;
   1585             mInstrumentation = instrumentation;
   1586             mRegistered = registered;
   1587             mLocation = new IntentReceiverLeaked(null);
   1588             mLocation.fillInStackTrace();
   1589         }
   1590 
   1591         void validate(Context context, Handler activityThread) {
   1592             if (mContext != context) {
   1593                 throw new IllegalStateException(
   1594                     "Receiver " + mReceiver +
   1595                     " registered with differing Context (was " +
   1596                     mContext + " now " + context + ")");
   1597             }
   1598             if (mActivityThread != activityThread) {
   1599                 throw new IllegalStateException(
   1600                     "Receiver " + mReceiver +
   1601                     " registered with differing handler (was " +
   1602                     mActivityThread + " now " + activityThread + ")");
   1603             }
   1604         }
   1605 
   1606         IntentReceiverLeaked getLocation() {
   1607             return mLocation;
   1608         }
   1609 
   1610         @UnsupportedAppUsage
   1611         BroadcastReceiver getIntentReceiver() {
   1612             return mReceiver;
   1613         }
   1614 
   1615         @UnsupportedAppUsage
   1616         IIntentReceiver getIIntentReceiver() {
   1617             return mIIntentReceiver;
   1618         }
   1619 
   1620         void setUnregisterLocation(RuntimeException ex) {
   1621             mUnregisterLocation = ex;
   1622         }
   1623 
   1624         RuntimeException getUnregisterLocation() {
   1625             return mUnregisterLocation;
   1626         }
   1627 
   1628         public void performReceive(Intent intent, int resultCode, String data,
   1629                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
   1630             final Args args = new Args(intent, resultCode, data, extras, ordered,
   1631                     sticky, sendingUser);
   1632             if (intent == null) {
   1633                 Log.wtf(TAG, "Null intent received");
   1634             } else {
   1635                 if (ActivityThread.DEBUG_BROADCAST) {
   1636                     int seq = intent.getIntExtra("seq", -1);
   1637                     Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
   1638                             + " seq=" + seq + " to " + mReceiver);
   1639                 }
   1640             }
   1641             if (intent == null || !mActivityThread.post(args.getRunnable())) {
   1642                 if (mRegistered && ordered) {
   1643                     IActivityManager mgr = ActivityManager.getService();
   1644                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
   1645                             "Finishing sync broadcast to " + mReceiver);
   1646                     args.sendFinished(mgr);
   1647                 }
   1648             }
   1649         }
   1650 
   1651     }
   1652 
   1653     @UnsupportedAppUsage
   1654     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
   1655             Context context, Handler handler, int flags) {
   1656         return getServiceDispatcherCommon(c, context, handler, null, flags);
   1657     }
   1658 
   1659     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
   1660             Context context, Executor executor, int flags) {
   1661         return getServiceDispatcherCommon(c, context, null, executor, flags);
   1662     }
   1663 
   1664     private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
   1665             Context context, Handler handler, Executor executor, int flags) {
   1666         synchronized (mServices) {
   1667             LoadedApk.ServiceDispatcher sd = null;
   1668             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
   1669             if (map != null) {
   1670                 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
   1671                 sd = map.get(c);
   1672             }
   1673             if (sd == null) {
   1674                 if (executor != null) {
   1675                     sd = new ServiceDispatcher(c, context, executor, flags);
   1676                 } else {
   1677                     sd = new ServiceDispatcher(c, context, handler, flags);
   1678                 }
   1679                 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
   1680                 if (map == null) {
   1681                     map = new ArrayMap<>();
   1682                     mServices.put(context, map);
   1683                 }
   1684                 map.put(c, sd);
   1685             } else {
   1686                 sd.validate(context, handler, executor);
   1687             }
   1688             return sd.getIServiceConnection();
   1689         }
   1690     }
   1691 
   1692     @UnsupportedAppUsage
   1693     public IServiceConnection lookupServiceDispatcher(ServiceConnection c,
   1694             Context context) {
   1695         synchronized (mServices) {
   1696             LoadedApk.ServiceDispatcher sd = null;
   1697             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
   1698             if (map != null) {
   1699                 sd = map.get(c);
   1700             }
   1701             return sd != null ? sd.getIServiceConnection() : null;
   1702         }
   1703     }
   1704 
   1705     public final IServiceConnection forgetServiceDispatcher(Context context,
   1706             ServiceConnection c) {
   1707         synchronized (mServices) {
   1708             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
   1709                     = mServices.get(context);
   1710             LoadedApk.ServiceDispatcher sd = null;
   1711             if (map != null) {
   1712                 sd = map.get(c);
   1713                 if (sd != null) {
   1714                     if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
   1715                     map.remove(c);
   1716                     sd.doForget();
   1717                     if (map.size() == 0) {
   1718                         mServices.remove(context);
   1719                     }
   1720                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
   1721                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
   1722                                 = mUnboundServices.get(context);
   1723                         if (holder == null) {
   1724                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
   1725                             mUnboundServices.put(context, holder);
   1726                         }
   1727                         RuntimeException ex = new IllegalArgumentException(
   1728                                 "Originally unbound here:");
   1729                         ex.fillInStackTrace();
   1730                         sd.setUnbindLocation(ex);
   1731                         holder.put(c, sd);
   1732                     }
   1733                     return sd.getIServiceConnection();
   1734                 }
   1735             }
   1736             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
   1737                     = mUnboundServices.get(context);
   1738             if (holder != null) {
   1739                 sd = holder.get(c);
   1740                 if (sd != null) {
   1741                     RuntimeException ex = sd.getUnbindLocation();
   1742                     throw new IllegalArgumentException(
   1743                             "Unbinding Service " + c
   1744                             + " that was already unbound", ex);
   1745                 }
   1746             }
   1747             if (context == null) {
   1748                 throw new IllegalStateException("Unbinding Service " + c
   1749                         + " from Context that is no longer in use: " + context);
   1750             } else {
   1751                 throw new IllegalArgumentException("Service not registered: " + c);
   1752             }
   1753         }
   1754     }
   1755 
   1756     static final class ServiceDispatcher {
   1757         private final ServiceDispatcher.InnerConnection mIServiceConnection;
   1758         @UnsupportedAppUsage
   1759         private final ServiceConnection mConnection;
   1760         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   1761         private final Context mContext;
   1762         private final Handler mActivityThread;
   1763         private final Executor mActivityExecutor;
   1764         private final ServiceConnectionLeaked mLocation;
   1765         private final int mFlags;
   1766 
   1767         private RuntimeException mUnbindLocation;
   1768 
   1769         private boolean mForgotten;
   1770 
   1771         private static class ConnectionInfo {
   1772             IBinder binder;
   1773             IBinder.DeathRecipient deathMonitor;
   1774         }
   1775 
   1776         private static class InnerConnection extends IServiceConnection.Stub {
   1777             @UnsupportedAppUsage
   1778             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
   1779 
   1780             InnerConnection(LoadedApk.ServiceDispatcher sd) {
   1781                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
   1782             }
   1783 
   1784             public void connected(ComponentName name, IBinder service, boolean dead)
   1785                     throws RemoteException {
   1786                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
   1787                 if (sd != null) {
   1788                     sd.connected(name, service, dead);
   1789                 }
   1790             }
   1791         }
   1792 
   1793         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
   1794             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
   1795 
   1796         @UnsupportedAppUsage
   1797         ServiceDispatcher(ServiceConnection conn,
   1798                 Context context, Handler activityThread, int flags) {
   1799             mIServiceConnection = new InnerConnection(this);
   1800             mConnection = conn;
   1801             mContext = context;
   1802             mActivityThread = activityThread;
   1803             mActivityExecutor = null;
   1804             mLocation = new ServiceConnectionLeaked(null);
   1805             mLocation.fillInStackTrace();
   1806             mFlags = flags;
   1807         }
   1808 
   1809         ServiceDispatcher(ServiceConnection conn,
   1810                 Context context, Executor activityExecutor, int flags) {
   1811             mIServiceConnection = new InnerConnection(this);
   1812             mConnection = conn;
   1813             mContext = context;
   1814             mActivityThread = null;
   1815             mActivityExecutor = activityExecutor;
   1816             mLocation = new ServiceConnectionLeaked(null);
   1817             mLocation.fillInStackTrace();
   1818             mFlags = flags;
   1819         }
   1820 
   1821         void validate(Context context, Handler activityThread, Executor activityExecutor) {
   1822             if (mContext != context) {
   1823                 throw new RuntimeException(
   1824                     "ServiceConnection " + mConnection +
   1825                     " registered with differing Context (was " +
   1826                     mContext + " now " + context + ")");
   1827             }
   1828             if (mActivityThread != activityThread) {
   1829                 throw new RuntimeException(
   1830                     "ServiceConnection " + mConnection +
   1831                     " registered with differing handler (was " +
   1832                     mActivityThread + " now " + activityThread + ")");
   1833             }
   1834             if (mActivityExecutor != activityExecutor) {
   1835                 throw new RuntimeException(
   1836                     "ServiceConnection " + mConnection +
   1837                     " registered with differing executor (was " +
   1838                     mActivityExecutor + " now " + activityExecutor + ")");
   1839             }
   1840         }
   1841 
   1842         void doForget() {
   1843             synchronized(this) {
   1844                 for (int i=0; i<mActiveConnections.size(); i++) {
   1845                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
   1846                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
   1847                 }
   1848                 mActiveConnections.clear();
   1849                 mForgotten = true;
   1850             }
   1851         }
   1852 
   1853         ServiceConnectionLeaked getLocation() {
   1854             return mLocation;
   1855         }
   1856 
   1857         ServiceConnection getServiceConnection() {
   1858             return mConnection;
   1859         }
   1860 
   1861         @UnsupportedAppUsage
   1862         IServiceConnection getIServiceConnection() {
   1863             return mIServiceConnection;
   1864         }
   1865 
   1866         int getFlags() {
   1867             return mFlags;
   1868         }
   1869 
   1870         void setUnbindLocation(RuntimeException ex) {
   1871             mUnbindLocation = ex;
   1872         }
   1873 
   1874         RuntimeException getUnbindLocation() {
   1875             return mUnbindLocation;
   1876         }
   1877 
   1878         public void connected(ComponentName name, IBinder service, boolean dead) {
   1879             if (mActivityExecutor != null) {
   1880                 mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
   1881             } else if (mActivityThread != null) {
   1882                 mActivityThread.post(new RunConnection(name, service, 0, dead));
   1883             } else {
   1884                 doConnected(name, service, dead);
   1885             }
   1886         }
   1887 
   1888         public void death(ComponentName name, IBinder service) {
   1889             if (mActivityExecutor != null) {
   1890                 mActivityExecutor.execute(new RunConnection(name, service, 1, false));
   1891             } else if (mActivityThread != null) {
   1892                 mActivityThread.post(new RunConnection(name, service, 1, false));
   1893             } else {
   1894                 doDeath(name, service);
   1895             }
   1896         }
   1897 
   1898         public void doConnected(ComponentName name, IBinder service, boolean dead) {
   1899             ServiceDispatcher.ConnectionInfo old;
   1900             ServiceDispatcher.ConnectionInfo info;
   1901 
   1902             synchronized (this) {
   1903                 if (mForgotten) {
   1904                     // We unbound before receiving the connection; ignore
   1905                     // any connection received.
   1906                     return;
   1907                 }
   1908                 old = mActiveConnections.get(name);
   1909                 if (old != null && old.binder == service) {
   1910                     // Huh, already have this one.  Oh well!
   1911                     return;
   1912                 }
   1913 
   1914                 if (service != null) {
   1915                     // A new service is being connected... set it all up.
   1916                     info = new ConnectionInfo();
   1917                     info.binder = service;
   1918                     info.deathMonitor = new DeathMonitor(name, service);
   1919                     try {
   1920                         service.linkToDeath(info.deathMonitor, 0);
   1921                         mActiveConnections.put(name, info);
   1922                     } catch (RemoteException e) {
   1923                         // This service was dead before we got it...  just
   1924                         // don't do anything with it.
   1925                         mActiveConnections.remove(name);
   1926                         return;
   1927                     }
   1928 
   1929                 } else {
   1930                     // The named service is being disconnected... clean up.
   1931                     mActiveConnections.remove(name);
   1932                 }
   1933 
   1934                 if (old != null) {
   1935                     old.binder.unlinkToDeath(old.deathMonitor, 0);
   1936                 }
   1937             }
   1938 
   1939             // If there was an old service, it is now disconnected.
   1940             if (old != null) {
   1941                 mConnection.onServiceDisconnected(name);
   1942             }
   1943             if (dead) {
   1944                 mConnection.onBindingDied(name);
   1945             }
   1946             // If there is a new viable service, it is now connected.
   1947             if (service != null) {
   1948                 mConnection.onServiceConnected(name, service);
   1949             } else {
   1950                 // The binding machinery worked, but the remote returned null from onBind().
   1951                 mConnection.onNullBinding(name);
   1952             }
   1953         }
   1954 
   1955         public void doDeath(ComponentName name, IBinder service) {
   1956             synchronized (this) {
   1957                 ConnectionInfo old = mActiveConnections.get(name);
   1958                 if (old == null || old.binder != service) {
   1959                     // Death for someone different than who we last
   1960                     // reported...  just ignore it.
   1961                     return;
   1962                 }
   1963                 mActiveConnections.remove(name);
   1964                 old.binder.unlinkToDeath(old.deathMonitor, 0);
   1965             }
   1966 
   1967             mConnection.onServiceDisconnected(name);
   1968         }
   1969 
   1970         private final class RunConnection implements Runnable {
   1971             RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
   1972                 mName = name;
   1973                 mService = service;
   1974                 mCommand = command;
   1975                 mDead = dead;
   1976             }
   1977 
   1978             public void run() {
   1979                 if (mCommand == 0) {
   1980                     doConnected(mName, mService, mDead);
   1981                 } else if (mCommand == 1) {
   1982                     doDeath(mName, mService);
   1983                 }
   1984             }
   1985 
   1986             final ComponentName mName;
   1987             final IBinder mService;
   1988             final int mCommand;
   1989             final boolean mDead;
   1990         }
   1991 
   1992         private final class DeathMonitor implements IBinder.DeathRecipient
   1993         {
   1994             DeathMonitor(ComponentName name, IBinder service) {
   1995                 mName = name;
   1996                 mService = service;
   1997             }
   1998 
   1999             public void binderDied() {
   2000                 death(mName, mService);
   2001             }
   2002 
   2003             final ComponentName mName;
   2004             final IBinder mService;
   2005         }
   2006     }
   2007 }
   2008