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