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