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.text.TextUtils;
     20 import android.util.ArrayMap;
     21 
     22 import android.content.BroadcastReceiver;
     23 import android.content.ComponentName;
     24 import android.content.Context;
     25 import android.content.IIntentReceiver;
     26 import android.content.Intent;
     27 import android.content.ServiceConnection;
     28 import android.content.pm.ApplicationInfo;
     29 import android.content.pm.IPackageManager;
     30 import android.content.pm.PackageManager;
     31 import android.content.res.AssetManager;
     32 import android.content.res.CompatibilityInfo;
     33 import android.content.res.Resources;
     34 import android.os.Bundle;
     35 import android.os.Handler;
     36 import android.os.IBinder;
     37 import android.os.Process;
     38 import android.os.RemoteException;
     39 import android.os.StrictMode;
     40 import android.os.Trace;
     41 import android.os.UserHandle;
     42 import android.util.AndroidRuntimeException;
     43 import android.util.Log;
     44 import android.util.Slog;
     45 import android.util.SparseArray;
     46 import android.view.DisplayAdjustments;
     47 import android.view.Display;
     48 import dalvik.system.VMRuntime;
     49 
     50 import java.io.File;
     51 import java.io.IOException;
     52 import java.io.InputStream;
     53 import java.lang.ref.WeakReference;
     54 import java.lang.reflect.InvocationTargetException;
     55 import java.lang.reflect.Method;
     56 import java.net.URL;
     57 import java.util.ArrayList;
     58 import java.util.Collections;
     59 import java.util.Enumeration;
     60 import java.util.Objects;
     61 
     62 final class IntentReceiverLeaked extends AndroidRuntimeException {
     63     public IntentReceiverLeaked(String msg) {
     64         super(msg);
     65     }
     66 }
     67 
     68 final class ServiceConnectionLeaked extends AndroidRuntimeException {
     69     public ServiceConnectionLeaked(String msg) {
     70         super(msg);
     71     }
     72 }
     73 
     74 /**
     75  * Local state maintained about a currently loaded .apk.
     76  * @hide
     77  */
     78 public final class LoadedApk {
     79 
     80     private static final String TAG = "LoadedApk";
     81 
     82     private final ActivityThread mActivityThread;
     83     private ApplicationInfo mApplicationInfo;
     84     final String mPackageName;
     85     private final String mAppDir;
     86     private final String mResDir;
     87     private final String[] mSplitAppDirs;
     88     private final String[] mSplitResDirs;
     89     private final String[] mOverlayDirs;
     90     private final String[] mSharedLibraries;
     91     private final String mDataDir;
     92     private final String mLibDir;
     93     private final File mDataDirFile;
     94     private final ClassLoader mBaseClassLoader;
     95     private final boolean mSecurityViolation;
     96     private final boolean mIncludeCode;
     97     private final boolean mRegisterPackage;
     98     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
     99     Resources mResources;
    100     private ClassLoader mClassLoader;
    101     private Application mApplication;
    102 
    103     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
    104         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
    105     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
    106         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
    107     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
    108         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
    109     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
    110         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
    111 
    112     int mClientCount = 0;
    113 
    114     Application getApplication() {
    115         return mApplication;
    116     }
    117 
    118     /**
    119      * Create information about a new .apk
    120      *
    121      * NOTE: This constructor is called with ActivityThread's lock held,
    122      * so MUST NOT call back out to the activity manager.
    123      */
    124     public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
    125             CompatibilityInfo compatInfo, ClassLoader baseLoader,
    126             boolean securityViolation, boolean includeCode, boolean registerPackage) {
    127         final int myUid = Process.myUid();
    128         aInfo = adjustNativeLibraryPaths(aInfo);
    129 
    130         mActivityThread = activityThread;
    131         mApplicationInfo = aInfo;
    132         mPackageName = aInfo.packageName;
    133         mAppDir = aInfo.sourceDir;
    134         mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
    135         mSplitAppDirs = aInfo.splitSourceDirs;
    136         mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
    137         mOverlayDirs = aInfo.resourceDirs;
    138         if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
    139             aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
    140                     mPackageName);
    141         }
    142         mSharedLibraries = aInfo.sharedLibraryFiles;
    143         mDataDir = aInfo.dataDir;
    144         mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
    145         mLibDir = aInfo.nativeLibraryDir;
    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             final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
    160 
    161             // If the runtimeIsa is the same as the primary isa, then we do nothing.
    162             // Everything will be set up correctly because info.nativeLibraryDir will
    163             // correspond to the right ISA.
    164             if (runtimeIsa.equals(secondaryIsa)) {
    165                 final ApplicationInfo modified = new ApplicationInfo(info);
    166                 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
    167                 return modified;
    168             }
    169         }
    170 
    171         return info;
    172     }
    173 
    174     /**
    175      * Create information about the system package.
    176      * Must call {@link #installSystemApplicationInfo} later.
    177      */
    178     LoadedApk(ActivityThread activityThread) {
    179         mActivityThread = activityThread;
    180         mApplicationInfo = new ApplicationInfo();
    181         mApplicationInfo.packageName = "android";
    182         mPackageName = "android";
    183         mAppDir = null;
    184         mResDir = null;
    185         mSplitAppDirs = null;
    186         mSplitResDirs = null;
    187         mOverlayDirs = null;
    188         mSharedLibraries = null;
    189         mDataDir = null;
    190         mDataDirFile = null;
    191         mLibDir = null;
    192         mBaseClassLoader = null;
    193         mSecurityViolation = false;
    194         mIncludeCode = true;
    195         mRegisterPackage = false;
    196         mClassLoader = ClassLoader.getSystemClassLoader();
    197         mResources = Resources.getSystem();
    198     }
    199 
    200     /**
    201      * Sets application info about the system package.
    202      */
    203     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
    204         assert info.packageName.equals("android");
    205         mApplicationInfo = info;
    206         mClassLoader = classLoader;
    207     }
    208 
    209     public String getPackageName() {
    210         return mPackageName;
    211     }
    212 
    213     public ApplicationInfo getApplicationInfo() {
    214         return mApplicationInfo;
    215     }
    216 
    217     public boolean isSecurityViolation() {
    218         return mSecurityViolation;
    219     }
    220 
    221     public CompatibilityInfo getCompatibilityInfo() {
    222         return mDisplayAdjustments.getCompatibilityInfo();
    223     }
    224 
    225     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
    226         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    227     }
    228 
    229     /**
    230      * Gets the array of shared libraries that are listed as
    231      * used by the given package.
    232      *
    233      * @param packageName the name of the package (note: not its
    234      * file name)
    235      * @return null-ok; the array of shared libraries, each one
    236      * a fully-qualified path
    237      */
    238     private static String[] getLibrariesFor(String packageName) {
    239         ApplicationInfo ai = null;
    240         try {
    241             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
    242                     PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
    243         } catch (RemoteException e) {
    244             throw new AssertionError(e);
    245         }
    246 
    247         if (ai == null) {
    248             return null;
    249         }
    250 
    251         return ai.sharedLibraryFiles;
    252     }
    253 
    254     public ClassLoader getClassLoader() {
    255         synchronized (this) {
    256             if (mClassLoader != null) {
    257                 return mClassLoader;
    258             }
    259 
    260             if (mIncludeCode && !mPackageName.equals("android")) {
    261                 // Avoid the binder call when the package is the current application package.
    262                 // The activity manager will perform ensure that dexopt is performed before
    263                 // spinning up the process.
    264                 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
    265                     final String isa = VMRuntime.getRuntime().vmInstructionSet();
    266                     try {
    267                         ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa);
    268                     } catch (RemoteException re) {
    269                         // Ignored.
    270                     }
    271                 }
    272 
    273                 final ArrayList<String> zipPaths = new ArrayList<>();
    274                 final ArrayList<String> libPaths = new ArrayList<>();
    275 
    276                 if (mRegisterPackage) {
    277                     try {
    278                         ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
    279                     } catch (RemoteException e) {
    280                     }
    281                 }
    282 
    283                 zipPaths.add(mAppDir);
    284                 if (mSplitAppDirs != null) {
    285                     Collections.addAll(zipPaths, mSplitAppDirs);
    286                 }
    287 
    288                 libPaths.add(mLibDir);
    289 
    290                 /*
    291                  * The following is a bit of a hack to inject
    292                  * instrumentation into the system: If the app
    293                  * being started matches one of the instrumentation names,
    294                  * then we combine both the "instrumentation" and
    295                  * "instrumented" app into the path, along with the
    296                  * concatenation of both apps' shared library lists.
    297                  */
    298 
    299                 String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
    300                 String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
    301                 String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
    302                 String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
    303 
    304                 String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
    305                 String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
    306                 String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
    307                 String[] instrumentationLibs = null;
    308 
    309                 if (mAppDir.equals(instrumentationAppDir)
    310                         || mAppDir.equals(instrumentedAppDir)) {
    311                     zipPaths.clear();
    312                     zipPaths.add(instrumentationAppDir);
    313                     if (instrumentationSplitAppDirs != null) {
    314                         Collections.addAll(zipPaths, instrumentationSplitAppDirs);
    315                     }
    316                     zipPaths.add(instrumentedAppDir);
    317                     if (instrumentedSplitAppDirs != null) {
    318                         Collections.addAll(zipPaths, instrumentedSplitAppDirs);
    319                     }
    320 
    321                     libPaths.clear();
    322                     libPaths.add(instrumentationLibDir);
    323                     libPaths.add(instrumentedLibDir);
    324 
    325                     if (!instrumentedAppDir.equals(instrumentationAppDir)) {
    326                         instrumentationLibs = getLibrariesFor(instrumentationPackageName);
    327                     }
    328                 }
    329 
    330                 if (mSharedLibraries != null) {
    331                     for (String lib : mSharedLibraries) {
    332                         if (!zipPaths.contains(lib)) {
    333                             zipPaths.add(0, lib);
    334                         }
    335                     }
    336                 }
    337 
    338                 if (instrumentationLibs != null) {
    339                     for (String lib : instrumentationLibs) {
    340                         if (!zipPaths.contains(lib)) {
    341                             zipPaths.add(0, lib);
    342                         }
    343                     }
    344                 }
    345 
    346                 final String zip = TextUtils.join(File.pathSeparator, zipPaths);
    347                 final String lib = TextUtils.join(File.pathSeparator, libPaths);
    348 
    349                 /*
    350                  * With all the combination done (if necessary, actually
    351                  * create the class loader.
    352                  */
    353 
    354                 if (ActivityThread.localLOGV)
    355                     Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + lib);
    356 
    357                 // Temporarily disable logging of disk reads on the Looper thread
    358                 // as this is early and necessary.
    359                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
    360 
    361                 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
    362                         mBaseClassLoader);
    363 
    364                 StrictMode.setThreadPolicy(oldPolicy);
    365             } else {
    366                 if (mBaseClassLoader == null) {
    367                     mClassLoader = ClassLoader.getSystemClassLoader();
    368                 } else {
    369                     mClassLoader = mBaseClassLoader;
    370                 }
    371             }
    372             return mClassLoader;
    373         }
    374     }
    375 
    376     /**
    377      * Setup value for Thread.getContextClassLoader(). If the
    378      * package will not run in in a VM with other packages, we set
    379      * the Java context ClassLoader to the
    380      * PackageInfo.getClassLoader value. However, if this VM can
    381      * contain multiple packages, we intead set the Java context
    382      * ClassLoader to a proxy that will warn about the use of Java
    383      * context ClassLoaders and then fall through to use the
    384      * system ClassLoader.
    385      *
    386      * <p> Note that this is similar to but not the same as the
    387      * android.content.Context.getClassLoader(). While both
    388      * context class loaders are typically set to the
    389      * PathClassLoader used to load the package archive in the
    390      * single application per VM case, a single Android process
    391      * may contain several Contexts executing on one thread with
    392      * their own logical ClassLoaders while the Java context
    393      * ClassLoader is a thread local. This is why in the case when
    394      * we have multiple packages per VM we do not set the Java
    395      * context ClassLoader to an arbitrary but instead warn the
    396      * user to set their own if we detect that they are using a
    397      * Java library that expects it to be set.
    398      */
    399     private void initializeJavaContextClassLoader() {
    400         IPackageManager pm = ActivityThread.getPackageManager();
    401         android.content.pm.PackageInfo pi;
    402         try {
    403             pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());
    404         } catch (RemoteException e) {
    405             throw new IllegalStateException("Unable to get package info for "
    406                     + mPackageName + "; is system dying?", e);
    407         }
    408         if (pi == null) {
    409             throw new IllegalStateException("Unable to get package info for "
    410                     + mPackageName + "; is package not installed?");
    411         }
    412         /*
    413          * Two possible indications that this package could be
    414          * sharing its virtual machine with other packages:
    415          *
    416          * 1.) the sharedUserId attribute is set in the manifest,
    417          *     indicating a request to share a VM with other
    418          *     packages with the same sharedUserId.
    419          *
    420          * 2.) the application element of the manifest has an
    421          *     attribute specifying a non-default process name,
    422          *     indicating the desire to run in another packages VM.
    423          */
    424         boolean sharedUserIdSet = (pi.sharedUserId != null);
    425         boolean processNameNotDefault =
    426             (pi.applicationInfo != null &&
    427              !mPackageName.equals(pi.applicationInfo.processName));
    428         boolean sharable = (sharedUserIdSet || processNameNotDefault);
    429         ClassLoader contextClassLoader =
    430             (sharable)
    431             ? new WarningContextClassLoader()
    432             : mClassLoader;
    433         Thread.currentThread().setContextClassLoader(contextClassLoader);
    434     }
    435 
    436     private static class WarningContextClassLoader extends ClassLoader {
    437 
    438         private static boolean warned = false;
    439 
    440         private void warn(String methodName) {
    441             if (warned) {
    442                 return;
    443             }
    444             warned = true;
    445             Thread.currentThread().setContextClassLoader(getParent());
    446             Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
    447                   "The class loader returned by " +
    448                   "Thread.getContextClassLoader() may fail for processes " +
    449                   "that host multiple applications. You should explicitly " +
    450                   "specify a context class loader. For example: " +
    451                   "Thread.setContextClassLoader(getClass().getClassLoader());");
    452         }
    453 
    454         @Override public URL getResource(String resName) {
    455             warn("getResource");
    456             return getParent().getResource(resName);
    457         }
    458 
    459         @Override public Enumeration<URL> getResources(String resName) throws IOException {
    460             warn("getResources");
    461             return getParent().getResources(resName);
    462         }
    463 
    464         @Override public InputStream getResourceAsStream(String resName) {
    465             warn("getResourceAsStream");
    466             return getParent().getResourceAsStream(resName);
    467         }
    468 
    469         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
    470             warn("loadClass");
    471             return getParent().loadClass(className);
    472         }
    473 
    474         @Override public void setClassAssertionStatus(String cname, boolean enable) {
    475             warn("setClassAssertionStatus");
    476             getParent().setClassAssertionStatus(cname, enable);
    477         }
    478 
    479         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
    480             warn("setPackageAssertionStatus");
    481             getParent().setPackageAssertionStatus(pname, enable);
    482         }
    483 
    484         @Override public void setDefaultAssertionStatus(boolean enable) {
    485             warn("setDefaultAssertionStatus");
    486             getParent().setDefaultAssertionStatus(enable);
    487         }
    488 
    489         @Override public void clearAssertionStatus() {
    490             warn("clearAssertionStatus");
    491             getParent().clearAssertionStatus();
    492         }
    493     }
    494 
    495     public String getAppDir() {
    496         return mAppDir;
    497     }
    498 
    499     public String getLibDir() {
    500         return mLibDir;
    501     }
    502 
    503     public String getResDir() {
    504         return mResDir;
    505     }
    506 
    507     public String[] getSplitAppDirs() {
    508         return mSplitAppDirs;
    509     }
    510 
    511     public String[] getSplitResDirs() {
    512         return mSplitResDirs;
    513     }
    514 
    515     public String[] getOverlayDirs() {
    516         return mOverlayDirs;
    517     }
    518 
    519     public String getDataDir() {
    520         return mDataDir;
    521     }
    522 
    523     public File getDataDirFile() {
    524         return mDataDirFile;
    525     }
    526 
    527     public AssetManager getAssets(ActivityThread mainThread) {
    528         return getResources(mainThread).getAssets();
    529     }
    530 
    531     public Resources getResources(ActivityThread mainThread) {
    532         if (mResources == null) {
    533             mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
    534                     mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
    535         }
    536         return mResources;
    537     }
    538 
    539     public Application makeApplication(boolean forceDefaultAppClass,
    540             Instrumentation instrumentation) {
    541         if (mApplication != null) {
    542             return mApplication;
    543         }
    544 
    545         Application app = null;
    546 
    547         String appClass = mApplicationInfo.className;
    548         if (forceDefaultAppClass || (appClass == null)) {
    549             appClass = "android.app.Application";
    550         }
    551 
    552         try {
    553             java.lang.ClassLoader cl = getClassLoader();
    554             if (!mPackageName.equals("android")) {
    555                 initializeJavaContextClassLoader();
    556             }
    557             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    558             app = mActivityThread.mInstrumentation.newApplication(
    559                     cl, appClass, appContext);
    560             appContext.setOuterContext(app);
    561         } catch (Exception e) {
    562             if (!mActivityThread.mInstrumentation.onException(app, e)) {
    563                 throw new RuntimeException(
    564                     "Unable to instantiate application " + appClass
    565                     + ": " + e.toString(), e);
    566             }
    567         }
    568         mActivityThread.mAllApplications.add(app);
    569         mApplication = app;
    570 
    571         if (instrumentation != null) {
    572             try {
    573                 instrumentation.callApplicationOnCreate(app);
    574             } catch (Exception e) {
    575                 if (!instrumentation.onException(app, e)) {
    576                     throw new RuntimeException(
    577                         "Unable to create application " + app.getClass().getName()
    578                         + ": " + e.toString(), e);
    579                 }
    580             }
    581         }
    582 
    583         // Rewrite the R 'constants' for all library apks.
    584         SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
    585                 .getAssignedPackageIdentifiers();
    586         final int N = packageIdentifiers.size();
    587         for (int i = 0; i < N; i++) {
    588             final int id = packageIdentifiers.keyAt(i);
    589             if (id == 0x01 || id == 0x7f) {
    590                 continue;
    591             }
    592 
    593             rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    594         }
    595 
    596         return app;
    597     }
    598 
    599     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
    600         final Class<?> rClazz;
    601         try {
    602             rClazz = cl.loadClass(packageName + ".R");
    603         } catch (ClassNotFoundException e) {
    604             // This is not necessarily an error, as some packages do not ship with resources
    605             // (or they do not need rewriting).
    606             Log.i(TAG, "No resource references to update in package " + packageName);
    607             return;
    608         }
    609 
    610         final Method callback;
    611         try {
    612             callback = rClazz.getMethod("onResourcesLoaded", int.class);
    613         } catch (NoSuchMethodException e) {
    614             // No rewriting to be done.
    615             return;
    616         }
    617 
    618         Throwable cause;
    619         try {
    620             callback.invoke(null, id);
    621             return;
    622         } catch (IllegalAccessException e) {
    623             cause = e;
    624         } catch (InvocationTargetException e) {
    625             cause = e.getCause();
    626         }
    627 
    628         throw new RuntimeException("Failed to rewrite resource references for " + packageName,
    629                 cause);
    630     }
    631 
    632     public void removeContextRegistrations(Context context,
    633             String who, String what) {
    634         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
    635         synchronized (mReceivers) {
    636             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
    637                     mReceivers.remove(context);
    638             if (rmap != null) {
    639                 for (int i = 0; i < rmap.size(); i++) {
    640                     LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
    641                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
    642                             what + " " + who + " has leaked IntentReceiver "
    643                             + rd.getIntentReceiver() + " that was " +
    644                             "originally registered here. Are you missing a " +
    645                             "call to unregisterReceiver()?");
    646                     leak.setStackTrace(rd.getLocation().getStackTrace());
    647                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
    648                     if (reportRegistrationLeaks) {
    649                         StrictMode.onIntentReceiverLeaked(leak);
    650                     }
    651                     try {
    652                         ActivityManagerNative.getDefault().unregisterReceiver(
    653                                 rd.getIIntentReceiver());
    654                     } catch (RemoteException e) {
    655                         // system crashed, nothing we can do
    656                     }
    657                 }
    658             }
    659             mUnregisteredReceivers.remove(context);
    660         }
    661 
    662         synchronized (mServices) {
    663             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
    664             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
    665                     mServices.remove(context);
    666             if (smap != null) {
    667                 for (int i = 0; i < smap.size(); i++) {
    668                     LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
    669                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
    670                             what + " " + who + " has leaked ServiceConnection "
    671                             + sd.getServiceConnection() + " that was originally bound here");
    672                     leak.setStackTrace(sd.getLocation().getStackTrace());
    673                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
    674                     if (reportRegistrationLeaks) {
    675                         StrictMode.onServiceConnectionLeaked(leak);
    676                     }
    677                     try {
    678                         ActivityManagerNative.getDefault().unbindService(
    679                                 sd.getIServiceConnection());
    680                     } catch (RemoteException e) {
    681                         // system crashed, nothing we can do
    682                     }
    683                     sd.doForget();
    684                 }
    685             }
    686             mUnboundServices.remove(context);
    687             //Slog.i(TAG, "Service registrations: " + mServices);
    688         }
    689     }
    690 
    691     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
    692             Context context, Handler handler,
    693             Instrumentation instrumentation, boolean registered) {
    694         synchronized (mReceivers) {
    695             LoadedApk.ReceiverDispatcher rd = null;
    696             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
    697             if (registered) {
    698                 map = mReceivers.get(context);
    699                 if (map != null) {
    700                     rd = map.get(r);
    701                 }
    702             }
    703             if (rd == null) {
    704                 rd = new ReceiverDispatcher(r, context, handler,
    705                         instrumentation, registered);
    706                 if (registered) {
    707                     if (map == null) {
    708                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
    709                         mReceivers.put(context, map);
    710                     }
    711                     map.put(r, rd);
    712                 }
    713             } else {
    714                 rd.validate(context, handler);
    715             }
    716             rd.mForgotten = false;
    717             return rd.getIIntentReceiver();
    718         }
    719     }
    720 
    721     public IIntentReceiver forgetReceiverDispatcher(Context context,
    722             BroadcastReceiver r) {
    723         synchronized (mReceivers) {
    724             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
    725             LoadedApk.ReceiverDispatcher rd = null;
    726             if (map != null) {
    727                 rd = map.get(r);
    728                 if (rd != null) {
    729                     map.remove(r);
    730                     if (map.size() == 0) {
    731                         mReceivers.remove(context);
    732                     }
    733                     if (r.getDebugUnregister()) {
    734                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
    735                                 = mUnregisteredReceivers.get(context);
    736                         if (holder == null) {
    737                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
    738                             mUnregisteredReceivers.put(context, holder);
    739                         }
    740                         RuntimeException ex = new IllegalArgumentException(
    741                                 "Originally unregistered here:");
    742                         ex.fillInStackTrace();
    743                         rd.setUnregisterLocation(ex);
    744                         holder.put(r, rd);
    745                     }
    746                     rd.mForgotten = true;
    747                     return rd.getIIntentReceiver();
    748                 }
    749             }
    750             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
    751                     = mUnregisteredReceivers.get(context);
    752             if (holder != null) {
    753                 rd = holder.get(r);
    754                 if (rd != null) {
    755                     RuntimeException ex = rd.getUnregisterLocation();
    756                     throw new IllegalArgumentException(
    757                             "Unregistering Receiver " + r
    758                             + " that was already unregistered", ex);
    759                 }
    760             }
    761             if (context == null) {
    762                 throw new IllegalStateException("Unbinding Receiver " + r
    763                         + " from Context that is no longer in use: " + context);
    764             } else {
    765                 throw new IllegalArgumentException("Receiver not registered: " + r);
    766             }
    767 
    768         }
    769     }
    770 
    771     static final class ReceiverDispatcher {
    772 
    773         final static class InnerReceiver extends IIntentReceiver.Stub {
    774             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
    775             final LoadedApk.ReceiverDispatcher mStrongRef;
    776 
    777             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
    778                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
    779                 mStrongRef = strong ? rd : null;
    780             }
    781             public void performReceive(Intent intent, int resultCode, String data,
    782                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    783                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
    784                 if (ActivityThread.DEBUG_BROADCAST) {
    785                     int seq = intent.getIntExtra("seq", -1);
    786                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
    787                             + " to " + (rd != null ? rd.mReceiver : null));
    788                 }
    789                 if (rd != null) {
    790                     rd.performReceive(intent, resultCode, data, extras,
    791                             ordered, sticky, sendingUser);
    792                 } else {
    793                     // The activity manager dispatched a broadcast to a registered
    794                     // receiver in this process, but before it could be delivered the
    795                     // receiver was unregistered.  Acknowledge the broadcast on its
    796                     // behalf so that the system's broadcast sequence can continue.
    797                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
    798                             "Finishing broadcast to unregistered receiver");
    799                     IActivityManager mgr = ActivityManagerNative.getDefault();
    800                     try {
    801                         if (extras != null) {
    802                             extras.setAllowFds(false);
    803                         }
    804                         mgr.finishReceiver(this, resultCode, data, extras, false);
    805                     } catch (RemoteException e) {
    806                         Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
    807                     }
    808                 }
    809             }
    810         }
    811 
    812         final IIntentReceiver.Stub mIIntentReceiver;
    813         final BroadcastReceiver mReceiver;
    814         final Context mContext;
    815         final Handler mActivityThread;
    816         final Instrumentation mInstrumentation;
    817         final boolean mRegistered;
    818         final IntentReceiverLeaked mLocation;
    819         RuntimeException mUnregisterLocation;
    820         boolean mForgotten;
    821 
    822         final class Args extends BroadcastReceiver.PendingResult implements Runnable {
    823             private Intent mCurIntent;
    824             private final boolean mOrdered;
    825 
    826             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
    827                     boolean ordered, boolean sticky, int sendingUser) {
    828                 super(resultCode, resultData, resultExtras,
    829                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
    830                         ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
    831                 mCurIntent = intent;
    832                 mOrdered = ordered;
    833             }
    834 
    835             public void run() {
    836                 final BroadcastReceiver receiver = mReceiver;
    837                 final boolean ordered = mOrdered;
    838 
    839                 if (ActivityThread.DEBUG_BROADCAST) {
    840                     int seq = mCurIntent.getIntExtra("seq", -1);
    841                     Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
    842                             + " seq=" + seq + " to " + mReceiver);
    843                     Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
    844                             + " mOrderedHint=" + ordered);
    845                 }
    846 
    847                 final IActivityManager mgr = ActivityManagerNative.getDefault();
    848                 final Intent intent = mCurIntent;
    849                 mCurIntent = null;
    850 
    851                 if (receiver == null || mForgotten) {
    852                     if (mRegistered && ordered) {
    853                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
    854                                 "Finishing null broadcast to " + mReceiver);
    855                         sendFinished(mgr);
    856                     }
    857                     return;
    858                 }
    859 
    860                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
    861                 try {
    862                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
    863                     intent.setExtrasClassLoader(cl);
    864                     setExtrasClassLoader(cl);
    865                     receiver.setPendingResult(this);
    866                     receiver.onReceive(mContext, intent);
    867                 } catch (Exception e) {
    868                     if (mRegistered && ordered) {
    869                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
    870                                 "Finishing failed broadcast to " + mReceiver);
    871                         sendFinished(mgr);
    872                     }
    873                     if (mInstrumentation == null ||
    874                             !mInstrumentation.onException(mReceiver, e)) {
    875                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    876                         throw new RuntimeException(
    877                             "Error receiving broadcast " + intent
    878                             + " in " + mReceiver, e);
    879                     }
    880                 }
    881 
    882                 if (receiver.getPendingResult() != null) {
    883                     finish();
    884                 }
    885                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    886             }
    887         }
    888 
    889         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
    890                 Handler activityThread, Instrumentation instrumentation,
    891                 boolean registered) {
    892             if (activityThread == null) {
    893                 throw new NullPointerException("Handler must not be null");
    894             }
    895 
    896             mIIntentReceiver = new InnerReceiver(this, !registered);
    897             mReceiver = receiver;
    898             mContext = context;
    899             mActivityThread = activityThread;
    900             mInstrumentation = instrumentation;
    901             mRegistered = registered;
    902             mLocation = new IntentReceiverLeaked(null);
    903             mLocation.fillInStackTrace();
    904         }
    905 
    906         void validate(Context context, Handler activityThread) {
    907             if (mContext != context) {
    908                 throw new IllegalStateException(
    909                     "Receiver " + mReceiver +
    910                     " registered with differing Context (was " +
    911                     mContext + " now " + context + ")");
    912             }
    913             if (mActivityThread != activityThread) {
    914                 throw new IllegalStateException(
    915                     "Receiver " + mReceiver +
    916                     " registered with differing handler (was " +
    917                     mActivityThread + " now " + activityThread + ")");
    918             }
    919         }
    920 
    921         IntentReceiverLeaked getLocation() {
    922             return mLocation;
    923         }
    924 
    925         BroadcastReceiver getIntentReceiver() {
    926             return mReceiver;
    927         }
    928 
    929         IIntentReceiver getIIntentReceiver() {
    930             return mIIntentReceiver;
    931         }
    932 
    933         void setUnregisterLocation(RuntimeException ex) {
    934             mUnregisterLocation = ex;
    935         }
    936 
    937         RuntimeException getUnregisterLocation() {
    938             return mUnregisterLocation;
    939         }
    940 
    941         public void performReceive(Intent intent, int resultCode, String data,
    942                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    943             if (ActivityThread.DEBUG_BROADCAST) {
    944                 int seq = intent.getIntExtra("seq", -1);
    945                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
    946                         + " to " + mReceiver);
    947             }
    948             Args args = new Args(intent, resultCode, data, extras, ordered,
    949                     sticky, sendingUser);
    950             if (!mActivityThread.post(args)) {
    951                 if (mRegistered && ordered) {
    952                     IActivityManager mgr = ActivityManagerNative.getDefault();
    953                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
    954                             "Finishing sync broadcast to " + mReceiver);
    955                     args.sendFinished(mgr);
    956                 }
    957             }
    958         }
    959 
    960     }
    961 
    962     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
    963             Context context, Handler handler, int flags) {
    964         synchronized (mServices) {
    965             LoadedApk.ServiceDispatcher sd = null;
    966             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
    967             if (map != null) {
    968                 sd = map.get(c);
    969             }
    970             if (sd == null) {
    971                 sd = new ServiceDispatcher(c, context, handler, flags);
    972                 if (map == null) {
    973                     map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
    974                     mServices.put(context, map);
    975                 }
    976                 map.put(c, sd);
    977             } else {
    978                 sd.validate(context, handler);
    979             }
    980             return sd.getIServiceConnection();
    981         }
    982     }
    983 
    984     public final IServiceConnection forgetServiceDispatcher(Context context,
    985             ServiceConnection c) {
    986         synchronized (mServices) {
    987             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
    988                     = mServices.get(context);
    989             LoadedApk.ServiceDispatcher sd = null;
    990             if (map != null) {
    991                 sd = map.get(c);
    992                 if (sd != null) {
    993                     map.remove(c);
    994                     sd.doForget();
    995                     if (map.size() == 0) {
    996                         mServices.remove(context);
    997                     }
    998                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
    999                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
   1000                                 = mUnboundServices.get(context);
   1001                         if (holder == null) {
   1002                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
   1003                             mUnboundServices.put(context, holder);
   1004                         }
   1005                         RuntimeException ex = new IllegalArgumentException(
   1006                                 "Originally unbound here:");
   1007                         ex.fillInStackTrace();
   1008                         sd.setUnbindLocation(ex);
   1009                         holder.put(c, sd);
   1010                     }
   1011                     return sd.getIServiceConnection();
   1012                 }
   1013             }
   1014             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
   1015                     = mUnboundServices.get(context);
   1016             if (holder != null) {
   1017                 sd = holder.get(c);
   1018                 if (sd != null) {
   1019                     RuntimeException ex = sd.getUnbindLocation();
   1020                     throw new IllegalArgumentException(
   1021                             "Unbinding Service " + c
   1022                             + " that was already unbound", ex);
   1023                 }
   1024             }
   1025             if (context == null) {
   1026                 throw new IllegalStateException("Unbinding Service " + c
   1027                         + " from Context that is no longer in use: " + context);
   1028             } else {
   1029                 throw new IllegalArgumentException("Service not registered: " + c);
   1030             }
   1031         }
   1032     }
   1033 
   1034     static final class ServiceDispatcher {
   1035         private final ServiceDispatcher.InnerConnection mIServiceConnection;
   1036         private final ServiceConnection mConnection;
   1037         private final Context mContext;
   1038         private final Handler mActivityThread;
   1039         private final ServiceConnectionLeaked mLocation;
   1040         private final int mFlags;
   1041 
   1042         private RuntimeException mUnbindLocation;
   1043 
   1044         private boolean mDied;
   1045         private boolean mForgotten;
   1046 
   1047         private static class ConnectionInfo {
   1048             IBinder binder;
   1049             IBinder.DeathRecipient deathMonitor;
   1050         }
   1051 
   1052         private static class InnerConnection extends IServiceConnection.Stub {
   1053             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
   1054 
   1055             InnerConnection(LoadedApk.ServiceDispatcher sd) {
   1056                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
   1057             }
   1058 
   1059             public void connected(ComponentName name, IBinder service) throws RemoteException {
   1060                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
   1061                 if (sd != null) {
   1062                     sd.connected(name, service);
   1063                 }
   1064             }
   1065         }
   1066 
   1067         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
   1068             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
   1069 
   1070         ServiceDispatcher(ServiceConnection conn,
   1071                 Context context, Handler activityThread, int flags) {
   1072             mIServiceConnection = new InnerConnection(this);
   1073             mConnection = conn;
   1074             mContext = context;
   1075             mActivityThread = activityThread;
   1076             mLocation = new ServiceConnectionLeaked(null);
   1077             mLocation.fillInStackTrace();
   1078             mFlags = flags;
   1079         }
   1080 
   1081         void validate(Context context, Handler activityThread) {
   1082             if (mContext != context) {
   1083                 throw new RuntimeException(
   1084                     "ServiceConnection " + mConnection +
   1085                     " registered with differing Context (was " +
   1086                     mContext + " now " + context + ")");
   1087             }
   1088             if (mActivityThread != activityThread) {
   1089                 throw new RuntimeException(
   1090                     "ServiceConnection " + mConnection +
   1091                     " registered with differing handler (was " +
   1092                     mActivityThread + " now " + activityThread + ")");
   1093             }
   1094         }
   1095 
   1096         void doForget() {
   1097             synchronized(this) {
   1098                 for (int i=0; i<mActiveConnections.size(); i++) {
   1099                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
   1100                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
   1101                 }
   1102                 mActiveConnections.clear();
   1103                 mForgotten = true;
   1104             }
   1105         }
   1106 
   1107         ServiceConnectionLeaked getLocation() {
   1108             return mLocation;
   1109         }
   1110 
   1111         ServiceConnection getServiceConnection() {
   1112             return mConnection;
   1113         }
   1114 
   1115         IServiceConnection getIServiceConnection() {
   1116             return mIServiceConnection;
   1117         }
   1118 
   1119         int getFlags() {
   1120             return mFlags;
   1121         }
   1122 
   1123         void setUnbindLocation(RuntimeException ex) {
   1124             mUnbindLocation = ex;
   1125         }
   1126 
   1127         RuntimeException getUnbindLocation() {
   1128             return mUnbindLocation;
   1129         }
   1130 
   1131         public void connected(ComponentName name, IBinder service) {
   1132             if (mActivityThread != null) {
   1133                 mActivityThread.post(new RunConnection(name, service, 0));
   1134             } else {
   1135                 doConnected(name, service);
   1136             }
   1137         }
   1138 
   1139         public void death(ComponentName name, IBinder service) {
   1140             ServiceDispatcher.ConnectionInfo old;
   1141 
   1142             synchronized (this) {
   1143                 mDied = true;
   1144                 old = mActiveConnections.remove(name);
   1145                 if (old == null || old.binder != service) {
   1146                     // Death for someone different than who we last
   1147                     // reported...  just ignore it.
   1148                     return;
   1149                 }
   1150                 old.binder.unlinkToDeath(old.deathMonitor, 0);
   1151             }
   1152 
   1153             if (mActivityThread != null) {
   1154                 mActivityThread.post(new RunConnection(name, service, 1));
   1155             } else {
   1156                 doDeath(name, service);
   1157             }
   1158         }
   1159 
   1160         public void doConnected(ComponentName name, IBinder service) {
   1161             ServiceDispatcher.ConnectionInfo old;
   1162             ServiceDispatcher.ConnectionInfo info;
   1163 
   1164             synchronized (this) {
   1165                 if (mForgotten) {
   1166                     // We unbound before receiving the connection; ignore
   1167                     // any connection received.
   1168                     return;
   1169                 }
   1170                 old = mActiveConnections.get(name);
   1171                 if (old != null && old.binder == service) {
   1172                     // Huh, already have this one.  Oh well!
   1173                     return;
   1174                 }
   1175 
   1176                 if (service != null) {
   1177                     // A new service is being connected... set it all up.
   1178                     mDied = false;
   1179                     info = new ConnectionInfo();
   1180                     info.binder = service;
   1181                     info.deathMonitor = new DeathMonitor(name, service);
   1182                     try {
   1183                         service.linkToDeath(info.deathMonitor, 0);
   1184                         mActiveConnections.put(name, info);
   1185                     } catch (RemoteException e) {
   1186                         // This service was dead before we got it...  just
   1187                         // don't do anything with it.
   1188                         mActiveConnections.remove(name);
   1189                         return;
   1190                     }
   1191 
   1192                 } else {
   1193                     // The named service is being disconnected... clean up.
   1194                     mActiveConnections.remove(name);
   1195                 }
   1196 
   1197                 if (old != null) {
   1198                     old.binder.unlinkToDeath(old.deathMonitor, 0);
   1199                 }
   1200             }
   1201 
   1202             // If there was an old service, it is not disconnected.
   1203             if (old != null) {
   1204                 mConnection.onServiceDisconnected(name);
   1205             }
   1206             // If there is a new service, it is now connected.
   1207             if (service != null) {
   1208                 mConnection.onServiceConnected(name, service);
   1209             }
   1210         }
   1211 
   1212         public void doDeath(ComponentName name, IBinder service) {
   1213             mConnection.onServiceDisconnected(name);
   1214         }
   1215 
   1216         private final class RunConnection implements Runnable {
   1217             RunConnection(ComponentName name, IBinder service, int command) {
   1218                 mName = name;
   1219                 mService = service;
   1220                 mCommand = command;
   1221             }
   1222 
   1223             public void run() {
   1224                 if (mCommand == 0) {
   1225                     doConnected(mName, mService);
   1226                 } else if (mCommand == 1) {
   1227                     doDeath(mName, mService);
   1228                 }
   1229             }
   1230 
   1231             final ComponentName mName;
   1232             final IBinder mService;
   1233             final int mCommand;
   1234         }
   1235 
   1236         private final class DeathMonitor implements IBinder.DeathRecipient
   1237         {
   1238             DeathMonitor(ComponentName name, IBinder service) {
   1239                 mName = name;
   1240                 mService = service;
   1241             }
   1242 
   1243             public void binderDied() {
   1244                 death(mName, mService);
   1245             }
   1246 
   1247             final ComponentName mName;
   1248             final IBinder mService;
   1249         }
   1250     }
   1251 }
   1252