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 {
IntentReceiverLeaked(String msg)76     public IntentReceiverLeaked(String msg) {
77         super(msg);
78     }
79 }
80 
81 final class ServiceConnectionLeaked extends AndroidRuntimeException {
ServiceConnectionLeaked(String msg)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 
getApplication()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      */
LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage)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 
adjustNativeLibraryPaths(ApplicationInfo info)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      */
LoadedApk(ActivityThread activityThread)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      */
installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader)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 
createAppFactory(ApplicationInfo appInfo, ClassLoader cl)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 
getAppFactory()235     public AppComponentFactory getAppFactory() {
236         return mAppComponentFactory;
237     }
238 
getPackageName()239     public String getPackageName() {
240         return mPackageName;
241     }
242 
getApplicationInfo()243     public ApplicationInfo getApplicationInfo() {
244         return mApplicationInfo;
245     }
246 
getTargetSdkVersion()247     public int getTargetSdkVersion() {
248         return mApplicationInfo.targetSdkVersion;
249     }
250 
isSecurityViolation()251     public boolean isSecurityViolation() {
252         return mSecurityViolation;
253     }
254 
getCompatibilityInfo()255     public CompatibilityInfo getCompatibilityInfo() {
256         return mDisplayAdjustments.getCompatibilityInfo();
257     }
258 
setCompatibilityInfo(CompatibilityInfo compatInfo)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      */
getLibrariesFor(String packageName)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      */
updateApplicationInfo(@onNull ApplicationInfo aInfo, @Nullable List<String> oldPaths)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 
setApplicationInfo(ApplicationInfo aInfo)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 
makePaths(ActivityThread activityThread, ApplicationInfo aInfo, List<String> outZipPaths)364     public static void makePaths(ActivityThread activityThread,
365                                  ApplicationInfo aInfo,
366                                  List<String> outZipPaths) {
367         makePaths(activityThread, false, aInfo, outZipPaths, null);
368     }
369 
makePaths(ActivityThread activityThread, boolean isBundledApp, ApplicationInfo aInfo, List<String> outZipPaths, List<String> outLibPaths)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      */
appendApkLibPathIfNeeded(@onNull String path, @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths)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 
SplitDependencyLoaderImpl(@onNull SparseArray<int[]> dependencies)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
isSplitCached(int splitIdx)531         protected boolean isSplitCached(int splitIdx) {
532             return mCachedClassLoaders[splitIdx] != null;
533         }
534 
535         @Override
constructSplit(int splitIdx, @NonNull int[] configSplitIndices, int parentSplitIdx)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 
ensureSplitLoaded(String splitName)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 
getClassLoaderForSplit(String splitName)579         ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException {
580             return mCachedClassLoaders[ensureSplitLoaded(splitName)];
581         }
582 
getSplitPathsForSplit(String splitName)583         String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException {
584             return mCachedResourcePaths[ensureSplitLoaded(splitName)];
585         }
586     }
587 
588     private SplitDependencyLoaderImpl mSplitLoader;
589 
getSplitClassLoader(String splitName)590     ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException {
591         if (mSplitLoader == null) {
592             return mClassLoader;
593         }
594         return mSplitLoader.getClassLoaderForSplit(splitName);
595     }
596 
getSplitPaths(String splitName)597     String[] getSplitPaths(String splitName) throws NameNotFoundException {
598         if (mSplitLoader == null) {
599             return mSplitResDirs;
600         }
601         return mSplitLoader.getSplitPathsForSplit(splitName);
602     }
603 
createOrUpdateClassLoaderLocked(List<String> addedPaths)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 
getClassLoader()807     public ClassLoader getClassLoader() {
808         synchronized (this) {
809             if (mClassLoader == null) {
810                 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
811             }
812             return mClassLoader;
813         }
814     }
815 
setupJitProfileSupport()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      */
initializeJavaContextClassLoader()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 
warn(String methodName)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 
getResource(String resName)934         @Override public URL getResource(String resName) {
935             warn("getResource");
936             return getParent().getResource(resName);
937         }
938 
getResources(String resName)939         @Override public Enumeration<URL> getResources(String resName) throws IOException {
940             warn("getResources");
941             return getParent().getResources(resName);
942         }
943 
getResourceAsStream(String resName)944         @Override public InputStream getResourceAsStream(String resName) {
945             warn("getResourceAsStream");
946             return getParent().getResourceAsStream(resName);
947         }
948 
loadClass(String className)949         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
950             warn("loadClass");
951             return getParent().loadClass(className);
952         }
953 
setClassAssertionStatus(String cname, boolean enable)954         @Override public void setClassAssertionStatus(String cname, boolean enable) {
955             warn("setClassAssertionStatus");
956             getParent().setClassAssertionStatus(cname, enable);
957         }
958 
setPackageAssertionStatus(String pname, boolean enable)959         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
960             warn("setPackageAssertionStatus");
961             getParent().setPackageAssertionStatus(pname, enable);
962         }
963 
setDefaultAssertionStatus(boolean enable)964         @Override public void setDefaultAssertionStatus(boolean enable) {
965             warn("setDefaultAssertionStatus");
966             getParent().setDefaultAssertionStatus(enable);
967         }
968 
clearAssertionStatus()969         @Override public void clearAssertionStatus() {
970             warn("clearAssertionStatus");
971             getParent().clearAssertionStatus();
972         }
973     }
974 
getAppDir()975     public String getAppDir() {
976         return mAppDir;
977     }
978 
getLibDir()979     public String getLibDir() {
980         return mLibDir;
981     }
982 
getResDir()983     public String getResDir() {
984         return mResDir;
985     }
986 
getSplitAppDirs()987     public String[] getSplitAppDirs() {
988         return mSplitAppDirs;
989     }
990 
getSplitResDirs()991     public String[] getSplitResDirs() {
992         return mSplitResDirs;
993     }
994 
getOverlayDirs()995     public String[] getOverlayDirs() {
996         return mOverlayDirs;
997     }
998 
getDataDir()999     public String getDataDir() {
1000         return mDataDir;
1001     }
1002 
getDataDirFile()1003     public File getDataDirFile() {
1004         return mDataDirFile;
1005     }
1006 
getDeviceProtectedDataDirFile()1007     public File getDeviceProtectedDataDirFile() {
1008         return mDeviceProtectedDataDirFile;
1009     }
1010 
getCredentialProtectedDataDirFile()1011     public File getCredentialProtectedDataDirFile() {
1012         return mCredentialProtectedDataDirFile;
1013     }
1014 
getAssets()1015     public AssetManager getAssets() {
1016         return getResources().getAssets();
1017     }
1018 
getResources()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 
makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation)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 
rewriteRValues(ClassLoader cl, String packageName, int id)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 
removeContextRegistrations(Context context, String who, String what)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 
getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)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 
forgetReceiverDispatcher(Context context, BroadcastReceiver r)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 
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)1283             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1284                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1285                 mStrongRef = strong ? rd : null;
1286             }
1287 
1288             @Override
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)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 
Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)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 
getRunnable()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 
ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)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 
validate(Context context, Handler activityThread)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 
getLocation()1447         IntentReceiverLeaked getLocation() {
1448             return mLocation;
1449         }
1450 
getIntentReceiver()1451         BroadcastReceiver getIntentReceiver() {
1452             return mReceiver;
1453         }
1454 
getIIntentReceiver()1455         IIntentReceiver getIIntentReceiver() {
1456             return mIIntentReceiver;
1457         }
1458 
setUnregisterLocation(RuntimeException ex)1459         void setUnregisterLocation(RuntimeException ex) {
1460             mUnregisterLocation = ex;
1461         }
1462 
getUnregisterLocation()1463         RuntimeException getUnregisterLocation() {
1464             return mUnregisterLocation;
1465         }
1466 
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)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 
getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)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 
forgetServiceDispatcher(Context context, ServiceConnection c)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 
InnerConnection(LoadedApk.ServiceDispatcher sd)1587             InnerConnection(LoadedApk.ServiceDispatcher sd) {
1588                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1589             }
1590 
connected(ComponentName name, IBinder service, boolean dead)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 
ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)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 
validate(Context context, Handler activityThread)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 
doForget()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 
getLocation()1640         ServiceConnectionLeaked getLocation() {
1641             return mLocation;
1642         }
1643 
getServiceConnection()1644         ServiceConnection getServiceConnection() {
1645             return mConnection;
1646         }
1647 
getIServiceConnection()1648         IServiceConnection getIServiceConnection() {
1649             return mIServiceConnection;
1650         }
1651 
getFlags()1652         int getFlags() {
1653             return mFlags;
1654         }
1655 
setUnbindLocation(RuntimeException ex)1656         void setUnbindLocation(RuntimeException ex) {
1657             mUnbindLocation = ex;
1658         }
1659 
getUnbindLocation()1660         RuntimeException getUnbindLocation() {
1661             return mUnbindLocation;
1662         }
1663 
connected(ComponentName name, IBinder service, boolean dead)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 
death(ComponentName name, IBinder service)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 
doConnected(ComponentName name, IBinder service, boolean dead)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 
doDeath(ComponentName name, IBinder service)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 {
RunConnection(ComponentName name, IBinder service, int command, boolean dead)1753             RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
1754                 mName = name;
1755                 mService = service;
1756                 mCommand = command;
1757                 mDead = dead;
1758             }
1759 
run()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         {
DeathMonitor(ComponentName name, IBinder service)1776             DeathMonitor(ComponentName name, IBinder service) {
1777                 mName = name;
1778                 mService = service;
1779             }
1780 
binderDied()1781             public void binderDied() {
1782                 death(mName, mService);
1783             }
1784 
1785             final ComponentName mName;
1786             final IBinder mService;
1787         }
1788     }
1789 }
1790