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