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