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