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