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