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