• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.IIntentReceiver;
26 import android.content.Intent;
27 import android.content.ServiceConnection;
28 import android.content.pm.ApplicationInfo;
29 import android.content.pm.IPackageManager;
30 import android.content.pm.PackageManager;
31 import android.content.pm.PackageManager.NameNotFoundException;
32 import android.content.pm.SharedLibraryInfo;
33 import android.content.pm.dex.ArtManager;
34 import android.content.pm.split.SplitDependencyLoader;
35 import android.content.res.AssetManager;
36 import android.content.res.CompatibilityInfo;
37 import android.content.res.Resources;
38 import android.os.Build;
39 import android.os.Bundle;
40 import android.os.FileUtils;
41 import android.os.GraphicsEnvironment;
42 import android.os.Handler;
43 import android.os.IBinder;
44 import android.os.Process;
45 import android.os.RemoteException;
46 import android.os.StrictMode;
47 import android.os.SystemProperties;
48 import android.os.Trace;
49 import android.os.UserHandle;
50 import android.provider.Settings;
51 import android.security.net.config.NetworkSecurityConfigProvider;
52 import android.sysprop.VndkProperties;
53 import android.text.TextUtils;
54 import android.util.AndroidRuntimeException;
55 import android.util.ArrayMap;
56 import android.util.Log;
57 import android.util.Slog;
58 import android.util.SparseArray;
59 import android.view.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         // Including an inaccessible dir in libraryPermittedPath would cause SELinux denials
806         // when the loader attempts to canonicalise the path. so we don't.
807         String libraryPermittedPath = canAccessDataDir() ? mDataDir : "";
808 
809         if (isBundledApp) {
810             // For bundled apps, add the base directory of the app (e.g.,
811             // /system/app/Foo/) to the permitted paths so that it can load libraries
812             // embedded in module apks under the directory. For now, GmsCore is relying
813             // on this, but this isn't specific to the app. Also note that, we don't
814             // need to do this for unbundled apps as entire /data is already set to
815             // the permitted paths for them.
816             libraryPermittedPath += File.pathSeparator
817                     + Paths.get(getAppDir()).getParent().toString();
818 
819             // This is necessary to grant bundled apps access to
820             // libraries located in subdirectories of /system/lib
821             libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
822         }
823 
824         final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
825 
826         if (mActivityThread != null) {
827             final String gpuDebugApp = mActivityThread.getStringCoreSetting(
828                     Settings.Global.GPU_DEBUG_APP, "");
829             if (!gpuDebugApp.isEmpty() && mPackageName.equals(gpuDebugApp)) {
830 
831                 // The current application is used to debug, attempt to get the debug layers.
832                 try {
833                     // Get the ApplicationInfo from PackageManager so that metadata fields present.
834                     final ApplicationInfo ai = ActivityThread.getPackageManager()
835                             .getApplicationInfo(mPackageName, PackageManager.GET_META_DATA,
836                                     UserHandle.myUserId());
837                     final String debugLayerPath = GraphicsEnvironment.getInstance()
838                             .getDebugLayerPathsFromSettings(mActivityThread.getCoreSettings(),
839                                     ActivityThread.getPackageManager(), mPackageName, ai);
840                     if (debugLayerPath != null) {
841                         libraryPermittedPath += File.pathSeparator + debugLayerPath;
842                     }
843                 } catch (RemoteException e) {
844                     // Unlikely to fail for applications, but in case of failure, something is wrong
845                     // inside the system server, hence just skip.
846                     Slog.e(ActivityThread.TAG,
847                             "RemoteException when fetching debug layer paths for: " + mPackageName);
848                 }
849             }
850         }
851 
852         // If we're not asked to include code, we construct a classloader that has
853         // no code path included. We still need to set up the library search paths
854         // and permitted path because NativeActivity relies on it (it attempts to
855         // call System.loadLibrary() on a classloader from a LoadedApk with
856         // mIncludeCode == false).
857         if (!mIncludeCode) {
858             if (mDefaultClassLoader == null) {
859                 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
860                 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(
861                         "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
862                         librarySearchPath, libraryPermittedPath, mBaseClassLoader,
863                         null /* classLoaderName */);
864                 setThreadPolicy(oldPolicy);
865                 mAppComponentFactory = AppComponentFactory.DEFAULT;
866             }
867 
868             if (mClassLoader == null) {
869                 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
870                         new ApplicationInfo(mApplicationInfo));
871             }
872 
873             return;
874         }
875 
876         /*
877          * With all the combination done (if necessary, actually create the java class
878          * loader and set up JIT profiling support if necessary.
879          *
880          * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
881          */
882         final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
883                 TextUtils.join(File.pathSeparator, zipPaths);
884 
885         if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
886                     ", JNI path: " + librarySearchPath);
887 
888         boolean needToSetupJitProfiles = false;
889         if (mDefaultClassLoader == null) {
890             // Temporarily disable logging of disk reads on the Looper thread
891             // as this is early and necessary.
892             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
893 
894             List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
895                     mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
896                     libraryPermittedPath);
897 
898             mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
899                     zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
900                     libraryPermittedPath, mBaseClassLoader,
901                     mApplicationInfo.classLoaderName, sharedLibraries);
902             mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
903 
904             setThreadPolicy(oldPolicy);
905             // Setup the class loader paths for profiling.
906             needToSetupJitProfiles = true;
907         }
908 
909         if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) {
910             // Temporarily disable logging of disk reads on the Looper thread as this is necessary
911             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
912             try {
913                 ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths);
914             } finally {
915                 setThreadPolicy(oldPolicy);
916             }
917         }
918 
919         if (addedPaths != null && addedPaths.size() > 0) {
920             final String add = TextUtils.join(File.pathSeparator, addedPaths);
921             ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add);
922             // Setup the new code paths for profiling.
923             needToSetupJitProfiles = true;
924         }
925 
926         // Setup jit profile support.
927         //
928         // It is ok to call this multiple times if the application gets updated with new splits.
929         // The runtime only keeps track of unique code paths and can handle re-registration of
930         // the same code path. There's no need to pass `addedPaths` since any new code paths
931         // are already in `mApplicationInfo`.
932         //
933         // It is NOT ok to call this function from the system_server (for any of the packages it
934         // loads code from) so we explicitly disallow it there.
935         //
936         // It is not ok to call this in a zygote context where mActivityThread is null.
937         if (needToSetupJitProfiles && !ActivityThread.isSystem() && mActivityThread != null) {
938             setupJitProfileSupport();
939         }
940 
941         // Call AppComponentFactory to select/create the main class loader of this app.
942         // Since this may call code in the app, mDefaultClassLoader must be fully set up
943         // before invoking the factory.
944         // Invoke with a copy of ApplicationInfo to protect against the app changing it.
945         if (mClassLoader == null) {
946             mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
947                     new ApplicationInfo(mApplicationInfo));
948         }
949     }
950 
951     /**
952      * Return whether we can access the package's private data directory in order to be able to
953      * load code from it.
954      */
canAccessDataDir()955     private boolean canAccessDataDir() {
956         // In a zygote context where mActivityThread is null we can't access the app data dir.
957         if (mActivityThread == null) {
958             return false;
959         }
960 
961         // A package can access its own data directory (the common case, so short-circuit it).
962         if (Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
963             return true;
964         }
965 
966         // Temporarily disable logging of disk reads on the Looper thread as this is necessary -
967         // and the loader will access the directory anyway if we don't check it.
968         StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
969         try {
970             // We are constructing a classloader for a different package. It is likely,
971             // but not certain, that we can't acccess its app data dir - so check.
972             return new File(mDataDir).canExecute();
973         } finally {
974             setThreadPolicy(oldPolicy);
975         }
976     }
977 
978     @UnsupportedAppUsage
getClassLoader()979     public ClassLoader getClassLoader() {
980         synchronized (this) {
981             if (mClassLoader == null) {
982                 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
983             }
984             return mClassLoader;
985         }
986     }
987 
setupJitProfileSupport()988     private void setupJitProfileSupport() {
989         if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
990             return;
991         }
992 
993         // If we use profiles, setup the dex reporter to notify package manager
994         // of any relevant dex loads. The idle maintenance job will use the information
995         // reported to optimize the loaded dex files.
996         // Note that we only need one global reporter per app.
997         // Make sure we do this before invoking app code for the first time so that we
998         // can capture the complete application startup.
999         BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
1000 
1001         // Only set up profile support if the loaded apk has the same uid as the
1002         // current process.
1003         // Currently, we do not support profiling across different apps.
1004         // (e.g. application's uid might be different when the code is
1005         // loaded by another app via createApplicationContext)
1006         if (mApplicationInfo.uid != Process.myUid()) {
1007             return;
1008         }
1009 
1010         final List<String> codePaths = new ArrayList<>();
1011         if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
1012             codePaths.add(mApplicationInfo.sourceDir);
1013         }
1014         if (mApplicationInfo.splitSourceDirs != null) {
1015             Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
1016         }
1017 
1018         if (codePaths.isEmpty()) {
1019             // If there are no code paths there's no need to setup a profile file and register with
1020             // the runtime,
1021             return;
1022         }
1023 
1024         for (int i = codePaths.size() - 1; i >= 0; i--) {
1025             String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1];
1026             String profileFile = ArtManager.getCurrentProfilePath(
1027                     mPackageName, UserHandle.myUserId(), splitName);
1028             VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)});
1029         }
1030 
1031         // Register the app data directory with the reporter. It will
1032         // help deciding whether or not a dex file is the primary apk or a
1033         // secondary dex.
1034         DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
1035     }
1036 
1037     /**
1038      * Setup value for Thread.getContextClassLoader(). If the
1039      * package will not run in in a VM with other packages, we set
1040      * the Java context ClassLoader to the
1041      * PackageInfo.getClassLoader value. However, if this VM can
1042      * contain multiple packages, we intead set the Java context
1043      * ClassLoader to a proxy that will warn about the use of Java
1044      * context ClassLoaders and then fall through to use the
1045      * system ClassLoader.
1046      *
1047      * <p> Note that this is similar to but not the same as the
1048      * android.content.Context.getClassLoader(). While both
1049      * context class loaders are typically set to the
1050      * PathClassLoader used to load the package archive in the
1051      * single application per VM case, a single Android process
1052      * may contain several Contexts executing on one thread with
1053      * their own logical ClassLoaders while the Java context
1054      * ClassLoader is a thread local. This is why in the case when
1055      * we have multiple packages per VM we do not set the Java
1056      * context ClassLoader to an arbitrary but instead warn the
1057      * user to set their own if we detect that they are using a
1058      * Java library that expects it to be set.
1059      */
initializeJavaContextClassLoader()1060     private void initializeJavaContextClassLoader() {
1061         IPackageManager pm = ActivityThread.getPackageManager();
1062         android.content.pm.PackageInfo pi =
1063                 PackageManager.getPackageInfoAsUserCached(
1064                         mPackageName,
1065                         PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
1066                         UserHandle.myUserId());
1067         /*
1068          * Two possible indications that this package could be
1069          * sharing its virtual machine with other packages:
1070          *
1071          * 1.) the sharedUserId attribute is set in the manifest,
1072          *     indicating a request to share a VM with other
1073          *     packages with the same sharedUserId.
1074          *
1075          * 2.) the application element of the manifest has an
1076          *     attribute specifying a non-default process name,
1077          *     indicating the desire to run in another packages VM.
1078          */
1079         boolean sharedUserIdSet = (pi.sharedUserId != null);
1080         boolean processNameNotDefault =
1081             (pi.applicationInfo != null &&
1082              !mPackageName.equals(pi.applicationInfo.processName));
1083         boolean sharable = (sharedUserIdSet || processNameNotDefault);
1084         ClassLoader contextClassLoader =
1085             (sharable)
1086             ? new WarningContextClassLoader()
1087             : mClassLoader;
1088         Thread.currentThread().setContextClassLoader(contextClassLoader);
1089     }
1090 
1091     private static class WarningContextClassLoader extends ClassLoader {
1092 
1093         private static boolean warned = false;
1094 
warn(String methodName)1095         private void warn(String methodName) {
1096             if (warned) {
1097                 return;
1098             }
1099             warned = true;
1100             Thread.currentThread().setContextClassLoader(getParent());
1101             Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
1102                   "The class loader returned by " +
1103                   "Thread.getContextClassLoader() may fail for processes " +
1104                   "that host multiple applications. You should explicitly " +
1105                   "specify a context class loader. For example: " +
1106                   "Thread.setContextClassLoader(getClass().getClassLoader());");
1107         }
1108 
getResource(String resName)1109         @Override public URL getResource(String resName) {
1110             warn("getResource");
1111             return getParent().getResource(resName);
1112         }
1113 
getResources(String resName)1114         @Override public Enumeration<URL> getResources(String resName) throws IOException {
1115             warn("getResources");
1116             return getParent().getResources(resName);
1117         }
1118 
getResourceAsStream(String resName)1119         @Override public InputStream getResourceAsStream(String resName) {
1120             warn("getResourceAsStream");
1121             return getParent().getResourceAsStream(resName);
1122         }
1123 
loadClass(String className)1124         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
1125             warn("loadClass");
1126             return getParent().loadClass(className);
1127         }
1128 
setClassAssertionStatus(String cname, boolean enable)1129         @Override public void setClassAssertionStatus(String cname, boolean enable) {
1130             warn("setClassAssertionStatus");
1131             getParent().setClassAssertionStatus(cname, enable);
1132         }
1133 
setPackageAssertionStatus(String pname, boolean enable)1134         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
1135             warn("setPackageAssertionStatus");
1136             getParent().setPackageAssertionStatus(pname, enable);
1137         }
1138 
setDefaultAssertionStatus(boolean enable)1139         @Override public void setDefaultAssertionStatus(boolean enable) {
1140             warn("setDefaultAssertionStatus");
1141             getParent().setDefaultAssertionStatus(enable);
1142         }
1143 
clearAssertionStatus()1144         @Override public void clearAssertionStatus() {
1145             warn("clearAssertionStatus");
1146             getParent().clearAssertionStatus();
1147         }
1148     }
1149 
1150     @UnsupportedAppUsage
getAppDir()1151     public String getAppDir() {
1152         return mAppDir;
1153     }
1154 
getLibDir()1155     public String getLibDir() {
1156         return mLibDir;
1157     }
1158 
1159     @UnsupportedAppUsage
getResDir()1160     public String getResDir() {
1161         return mResDir;
1162     }
1163 
getSplitAppDirs()1164     public String[] getSplitAppDirs() {
1165         return mSplitAppDirs;
1166     }
1167 
1168     @UnsupportedAppUsage
getSplitResDirs()1169     public String[] getSplitResDirs() {
1170         return mSplitResDirs;
1171     }
1172 
1173     @UnsupportedAppUsage
getOverlayDirs()1174     public String[] getOverlayDirs() {
1175         return mOverlayDirs;
1176     }
1177 
getDataDir()1178     public String getDataDir() {
1179         return mDataDir;
1180     }
1181 
1182     @UnsupportedAppUsage
getDataDirFile()1183     public File getDataDirFile() {
1184         return mDataDirFile;
1185     }
1186 
getDeviceProtectedDataDirFile()1187     public File getDeviceProtectedDataDirFile() {
1188         return mDeviceProtectedDataDirFile;
1189     }
1190 
getCredentialProtectedDataDirFile()1191     public File getCredentialProtectedDataDirFile() {
1192         return mCredentialProtectedDataDirFile;
1193     }
1194 
1195     @UnsupportedAppUsage
getAssets()1196     public AssetManager getAssets() {
1197         return getResources().getAssets();
1198     }
1199 
1200     @UnsupportedAppUsage
getResources()1201     public Resources getResources() {
1202         if (mResources == null) {
1203             final String[] splitPaths;
1204             try {
1205                 splitPaths = getSplitPaths(null);
1206             } catch (NameNotFoundException e) {
1207                 // This should never fail.
1208                 throw new AssertionError("null split not found");
1209             }
1210 
1211             mResources = ResourcesManager.getInstance().getResources(null, mResDir,
1212                     splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
1213                     Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
1214                     getClassLoader(), null);
1215         }
1216         return mResources;
1217     }
1218 
1219     @UnsupportedAppUsage
makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation)1220     public Application makeApplication(boolean forceDefaultAppClass,
1221             Instrumentation instrumentation) {
1222         if (mApplication != null) {
1223             return mApplication;
1224         }
1225 
1226         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
1227 
1228         Application app = null;
1229 
1230         String appClass = mApplicationInfo.className;
1231         if (forceDefaultAppClass || (appClass == null)) {
1232             appClass = "android.app.Application";
1233         }
1234 
1235         try {
1236             final java.lang.ClassLoader cl = getClassLoader();
1237             if (!mPackageName.equals("android")) {
1238                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1239                         "initializeJavaContextClassLoader");
1240                 initializeJavaContextClassLoader();
1241                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1242             }
1243 
1244             // Rewrite the R 'constants' for all library apks.
1245             SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
1246                     false, false);
1247             for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
1248                 final int id = packageIdentifiers.keyAt(i);
1249                 if (id == 0x01 || id == 0x7f) {
1250                     continue;
1251                 }
1252 
1253                 rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
1254             }
1255 
1256             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
1257             // The network security config needs to be aware of multiple
1258             // applications in the same process to handle discrepancies
1259             NetworkSecurityConfigProvider.handleNewApplication(appContext);
1260             app = mActivityThread.mInstrumentation.newApplication(
1261                     cl, appClass, appContext);
1262             appContext.setOuterContext(app);
1263         } catch (Exception e) {
1264             if (!mActivityThread.mInstrumentation.onException(app, e)) {
1265                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1266                 throw new RuntimeException(
1267                     "Unable to instantiate application " + appClass
1268                     + ": " + e.toString(), e);
1269             }
1270         }
1271         mActivityThread.mAllApplications.add(app);
1272         mApplication = app;
1273 
1274         if (instrumentation != null) {
1275             try {
1276                 instrumentation.callApplicationOnCreate(app);
1277             } catch (Exception e) {
1278                 if (!instrumentation.onException(app, e)) {
1279                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1280                     throw new RuntimeException(
1281                         "Unable to create application " + app.getClass().getName()
1282                         + ": " + e.toString(), e);
1283                 }
1284             }
1285         }
1286 
1287         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1288 
1289         return app;
1290     }
1291 
1292     @UnsupportedAppUsage
rewriteRValues(ClassLoader cl, String packageName, int id)1293     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
1294         final Class<?> rClazz;
1295         try {
1296             rClazz = cl.loadClass(packageName + ".R");
1297         } catch (ClassNotFoundException e) {
1298             // This is not necessarily an error, as some packages do not ship with resources
1299             // (or they do not need rewriting).
1300             Log.i(TAG, "No resource references to update in package " + packageName);
1301             return;
1302         }
1303 
1304         final Method callback;
1305         try {
1306             callback = rClazz.getMethod("onResourcesLoaded", int.class);
1307         } catch (NoSuchMethodException e) {
1308             // No rewriting to be done.
1309             return;
1310         }
1311 
1312         Throwable cause;
1313         try {
1314             callback.invoke(null, id);
1315             return;
1316         } catch (IllegalAccessException e) {
1317             cause = e;
1318         } catch (InvocationTargetException e) {
1319             cause = e.getCause();
1320         }
1321 
1322         throw new RuntimeException("Failed to rewrite resource references for " + packageName,
1323                 cause);
1324     }
1325 
removeContextRegistrations(Context context, String who, String what)1326     public void removeContextRegistrations(Context context,
1327             String who, String what) {
1328         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
1329         synchronized (mReceivers) {
1330             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
1331                     mReceivers.remove(context);
1332             if (rmap != null) {
1333                 for (int i = 0; i < rmap.size(); i++) {
1334                     LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
1335                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
1336                             what + " " + who + " has leaked IntentReceiver "
1337                             + rd.getIntentReceiver() + " that was " +
1338                             "originally registered here. Are you missing a " +
1339                             "call to unregisterReceiver()?");
1340                     leak.setStackTrace(rd.getLocation().getStackTrace());
1341                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1342                     if (reportRegistrationLeaks) {
1343                         StrictMode.onIntentReceiverLeaked(leak);
1344                     }
1345                     try {
1346                         ActivityManager.getService().unregisterReceiver(
1347                                 rd.getIIntentReceiver());
1348                     } catch (RemoteException e) {
1349                         throw e.rethrowFromSystemServer();
1350                     }
1351                 }
1352             }
1353             mUnregisteredReceivers.remove(context);
1354         }
1355 
1356         synchronized (mServices) {
1357             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
1358             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
1359                     mServices.remove(context);
1360             if (smap != null) {
1361                 for (int i = 0; i < smap.size(); i++) {
1362                     LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
1363                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
1364                             what + " " + who + " has leaked ServiceConnection "
1365                             + sd.getServiceConnection() + " that was originally bound here");
1366                     leak.setStackTrace(sd.getLocation().getStackTrace());
1367                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1368                     if (reportRegistrationLeaks) {
1369                         StrictMode.onServiceConnectionLeaked(leak);
1370                     }
1371                     try {
1372                         ActivityManager.getService().unbindService(
1373                                 sd.getIServiceConnection());
1374                     } catch (RemoteException e) {
1375                         throw e.rethrowFromSystemServer();
1376                     }
1377                     sd.doForget();
1378                 }
1379             }
1380             mUnboundServices.remove(context);
1381             //Slog.i(TAG, "Service registrations: " + mServices);
1382         }
1383     }
1384 
getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)1385     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
1386             Context context, Handler handler,
1387             Instrumentation instrumentation, boolean registered) {
1388         synchronized (mReceivers) {
1389             LoadedApk.ReceiverDispatcher rd = null;
1390             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
1391             if (registered) {
1392                 map = mReceivers.get(context);
1393                 if (map != null) {
1394                     rd = map.get(r);
1395                 }
1396             }
1397             if (rd == null) {
1398                 rd = new ReceiverDispatcher(r, context, handler,
1399                         instrumentation, registered);
1400                 if (registered) {
1401                     if (map == null) {
1402                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
1403                         mReceivers.put(context, map);
1404                     }
1405                     map.put(r, rd);
1406                 }
1407             } else {
1408                 rd.validate(context, handler);
1409             }
1410             rd.mForgotten = false;
1411             return rd.getIIntentReceiver();
1412         }
1413     }
1414 
forgetReceiverDispatcher(Context context, BroadcastReceiver r)1415     public IIntentReceiver forgetReceiverDispatcher(Context context,
1416             BroadcastReceiver r) {
1417         synchronized (mReceivers) {
1418             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
1419             LoadedApk.ReceiverDispatcher rd = null;
1420             if (map != null) {
1421                 rd = map.get(r);
1422                 if (rd != null) {
1423                     map.remove(r);
1424                     if (map.size() == 0) {
1425                         mReceivers.remove(context);
1426                     }
1427                     if (r.getDebugUnregister()) {
1428                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
1429                                 = mUnregisteredReceivers.get(context);
1430                         if (holder == null) {
1431                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
1432                             mUnregisteredReceivers.put(context, holder);
1433                         }
1434                         RuntimeException ex = new IllegalArgumentException(
1435                                 "Originally unregistered here:");
1436                         ex.fillInStackTrace();
1437                         rd.setUnregisterLocation(ex);
1438                         holder.put(r, rd);
1439                     }
1440                     rd.mForgotten = true;
1441                     return rd.getIIntentReceiver();
1442                 }
1443             }
1444             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
1445                     = mUnregisteredReceivers.get(context);
1446             if (holder != null) {
1447                 rd = holder.get(r);
1448                 if (rd != null) {
1449                     RuntimeException ex = rd.getUnregisterLocation();
1450                     throw new IllegalArgumentException(
1451                             "Unregistering Receiver " + r
1452                             + " that was already unregistered", ex);
1453                 }
1454             }
1455             if (context == null) {
1456                 throw new IllegalStateException("Unbinding Receiver " + r
1457                         + " from Context that is no longer in use: " + context);
1458             } else {
1459                 throw new IllegalArgumentException("Receiver not registered: " + r);
1460             }
1461 
1462         }
1463     }
1464 
1465     static final class ReceiverDispatcher {
1466 
1467         final static class InnerReceiver extends IIntentReceiver.Stub {
1468             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1469             final LoadedApk.ReceiverDispatcher mStrongRef;
1470 
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)1471             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1472                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1473                 mStrongRef = strong ? rd : null;
1474             }
1475 
1476             @Override
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1477             public void performReceive(Intent intent, int resultCode, String data,
1478                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1479                 final LoadedApk.ReceiverDispatcher rd;
1480                 if (intent == null) {
1481                     Log.wtf(TAG, "Null intent received");
1482                     rd = null;
1483                 } else {
1484                     rd = mDispatcher.get();
1485                 }
1486                 if (ActivityThread.DEBUG_BROADCAST) {
1487                     int seq = intent.getIntExtra("seq", -1);
1488                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1489                             + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
1490                 }
1491                 if (rd != null) {
1492                     rd.performReceive(intent, resultCode, data, extras,
1493                             ordered, sticky, sendingUser);
1494                 } else {
1495                     // The activity manager dispatched a broadcast to a registered
1496                     // receiver in this process, but before it could be delivered the
1497                     // receiver was unregistered.  Acknowledge the broadcast on its
1498                     // behalf so that the system's broadcast sequence can continue.
1499                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1500                             "Finishing broadcast to unregistered receiver");
1501                     IActivityManager mgr = ActivityManager.getService();
1502                     try {
1503                         if (extras != null) {
1504                             extras.setAllowFds(false);
1505                         }
1506                         mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
1507                     } catch (RemoteException e) {
1508                         throw e.rethrowFromSystemServer();
1509                     }
1510                 }
1511             }
1512         }
1513 
1514         final IIntentReceiver.Stub mIIntentReceiver;
1515         @UnsupportedAppUsage
1516         final BroadcastReceiver mReceiver;
1517         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1518         final Context mContext;
1519         final Handler mActivityThread;
1520         final Instrumentation mInstrumentation;
1521         final boolean mRegistered;
1522         final IntentReceiverLeaked mLocation;
1523         RuntimeException mUnregisterLocation;
1524         boolean mForgotten;
1525 
1526         final class Args extends BroadcastReceiver.PendingResult {
1527             private Intent mCurIntent;
1528             private final boolean mOrdered;
1529             private boolean mDispatched;
1530             private boolean mRunCalled;
1531 
Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)1532             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
1533                     boolean ordered, boolean sticky, int sendingUser) {
1534                 super(resultCode, resultData, resultExtras,
1535                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1536                         sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
1537                 mCurIntent = intent;
1538                 mOrdered = ordered;
1539             }
1540 
getRunnable()1541             public final Runnable getRunnable() {
1542                 return () -> {
1543                     final BroadcastReceiver receiver = mReceiver;
1544                     final boolean ordered = mOrdered;
1545 
1546                     if (ActivityThread.DEBUG_BROADCAST) {
1547                         int seq = mCurIntent.getIntExtra("seq", -1);
1548                         Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1549                                 + " seq=" + seq + " to " + mReceiver);
1550                         Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
1551                                 + " mOrderedHint=" + ordered);
1552                     }
1553 
1554                     final IActivityManager mgr = ActivityManager.getService();
1555                     final Intent intent = mCurIntent;
1556                     if (intent == null) {
1557                         Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
1558                                 + (mRunCalled ? ", run() has already been called" : ""));
1559                     }
1560 
1561                     mCurIntent = null;
1562                     mDispatched = true;
1563                     mRunCalled = true;
1564                     if (receiver == null || intent == null || mForgotten) {
1565                         if (mRegistered && ordered) {
1566                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1567                                     "Finishing null broadcast to " + mReceiver);
1568                             sendFinished(mgr);
1569                         }
1570                         return;
1571                     }
1572 
1573                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
1574                     try {
1575                         ClassLoader cl = mReceiver.getClass().getClassLoader();
1576                         intent.setExtrasClassLoader(cl);
1577                         intent.prepareToEnterProcess();
1578                         setExtrasClassLoader(cl);
1579                         receiver.setPendingResult(this);
1580                         receiver.onReceive(mContext, intent);
1581                     } catch (Exception e) {
1582                         if (mRegistered && ordered) {
1583                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1584                                     "Finishing failed broadcast to " + mReceiver);
1585                             sendFinished(mgr);
1586                         }
1587                         if (mInstrumentation == null ||
1588                                 !mInstrumentation.onException(mReceiver, e)) {
1589                             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1590                             throw new RuntimeException(
1591                                     "Error receiving broadcast " + intent
1592                                             + " in " + mReceiver, e);
1593                         }
1594                     }
1595 
1596                     if (receiver.getPendingResult() != null) {
1597                         finish();
1598                     }
1599                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1600                 };
1601             }
1602         }
1603 
ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)1604         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1605                 Handler activityThread, Instrumentation instrumentation,
1606                 boolean registered) {
1607             if (activityThread == null) {
1608                 throw new NullPointerException("Handler must not be null");
1609             }
1610 
1611             mIIntentReceiver = new InnerReceiver(this, !registered);
1612             mReceiver = receiver;
1613             mContext = context;
1614             mActivityThread = activityThread;
1615             mInstrumentation = instrumentation;
1616             mRegistered = registered;
1617             mLocation = new IntentReceiverLeaked(null);
1618             mLocation.fillInStackTrace();
1619         }
1620 
validate(Context context, Handler activityThread)1621         void validate(Context context, Handler activityThread) {
1622             if (mContext != context) {
1623                 throw new IllegalStateException(
1624                     "Receiver " + mReceiver +
1625                     " registered with differing Context (was " +
1626                     mContext + " now " + context + ")");
1627             }
1628             if (mActivityThread != activityThread) {
1629                 throw new IllegalStateException(
1630                     "Receiver " + mReceiver +
1631                     " registered with differing handler (was " +
1632                     mActivityThread + " now " + activityThread + ")");
1633             }
1634         }
1635 
getLocation()1636         IntentReceiverLeaked getLocation() {
1637             return mLocation;
1638         }
1639 
1640         @UnsupportedAppUsage
getIntentReceiver()1641         BroadcastReceiver getIntentReceiver() {
1642             return mReceiver;
1643         }
1644 
1645         @UnsupportedAppUsage
getIIntentReceiver()1646         IIntentReceiver getIIntentReceiver() {
1647             return mIIntentReceiver;
1648         }
1649 
setUnregisterLocation(RuntimeException ex)1650         void setUnregisterLocation(RuntimeException ex) {
1651             mUnregisterLocation = ex;
1652         }
1653 
getUnregisterLocation()1654         RuntimeException getUnregisterLocation() {
1655             return mUnregisterLocation;
1656         }
1657 
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1658         public void performReceive(Intent intent, int resultCode, String data,
1659                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1660             final Args args = new Args(intent, resultCode, data, extras, ordered,
1661                     sticky, sendingUser);
1662             if (intent == null) {
1663                 Log.wtf(TAG, "Null intent received");
1664             } else {
1665                 if (ActivityThread.DEBUG_BROADCAST) {
1666                     int seq = intent.getIntExtra("seq", -1);
1667                     Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1668                             + " seq=" + seq + " to " + mReceiver);
1669                 }
1670             }
1671             if (intent == null || !mActivityThread.post(args.getRunnable())) {
1672                 if (mRegistered && ordered) {
1673                     IActivityManager mgr = ActivityManager.getService();
1674                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1675                             "Finishing sync broadcast to " + mReceiver);
1676                     args.sendFinished(mgr);
1677                 }
1678             }
1679         }
1680 
1681     }
1682 
1683     @UnsupportedAppUsage
getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)1684     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1685             Context context, Handler handler, int flags) {
1686         return getServiceDispatcherCommon(c, context, handler, null, flags);
1687     }
1688 
getServiceDispatcher(ServiceConnection c, Context context, Executor executor, int flags)1689     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1690             Context context, Executor executor, int flags) {
1691         return getServiceDispatcherCommon(c, context, null, executor, flags);
1692     }
1693 
getServiceDispatcherCommon(ServiceConnection c, Context context, Handler handler, Executor executor, int flags)1694     private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
1695             Context context, Handler handler, Executor executor, int flags) {
1696         synchronized (mServices) {
1697             LoadedApk.ServiceDispatcher sd = null;
1698             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
1699             if (map != null) {
1700                 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
1701                 sd = map.get(c);
1702             }
1703             if (sd == null) {
1704                 if (executor != null) {
1705                     sd = new ServiceDispatcher(c, context, executor, flags);
1706                 } else {
1707                     sd = new ServiceDispatcher(c, context, handler, flags);
1708                 }
1709                 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
1710                 if (map == null) {
1711                     map = new ArrayMap<>();
1712                     mServices.put(context, map);
1713                 }
1714                 map.put(c, sd);
1715             } else {
1716                 sd.validate(context, handler, executor);
1717             }
1718             return sd.getIServiceConnection();
1719         }
1720     }
1721 
1722     @UnsupportedAppUsage
lookupServiceDispatcher(ServiceConnection c, Context context)1723     public IServiceConnection lookupServiceDispatcher(ServiceConnection c,
1724             Context context) {
1725         synchronized (mServices) {
1726             LoadedApk.ServiceDispatcher sd = null;
1727             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
1728             if (map != null) {
1729                 sd = map.get(c);
1730             }
1731             return sd != null ? sd.getIServiceConnection() : null;
1732         }
1733     }
1734 
forgetServiceDispatcher(Context context, ServiceConnection c)1735     public final IServiceConnection forgetServiceDispatcher(Context context,
1736             ServiceConnection c) {
1737         synchronized (mServices) {
1738             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
1739                     = mServices.get(context);
1740             LoadedApk.ServiceDispatcher sd = null;
1741             if (map != null) {
1742                 sd = map.get(c);
1743                 if (sd != null) {
1744                     if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
1745                     map.remove(c);
1746                     sd.doForget();
1747                     if (map.size() == 0) {
1748                         mServices.remove(context);
1749                     }
1750                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1751                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1752                                 = mUnboundServices.get(context);
1753                         if (holder == null) {
1754                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
1755                             mUnboundServices.put(context, holder);
1756                         }
1757                         RuntimeException ex = new IllegalArgumentException(
1758                                 "Originally unbound here:");
1759                         ex.fillInStackTrace();
1760                         sd.setUnbindLocation(ex);
1761                         holder.put(c, sd);
1762                     }
1763                     return sd.getIServiceConnection();
1764                 }
1765             }
1766             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1767                     = mUnboundServices.get(context);
1768             if (holder != null) {
1769                 sd = holder.get(c);
1770                 if (sd != null) {
1771                     RuntimeException ex = sd.getUnbindLocation();
1772                     throw new IllegalArgumentException(
1773                             "Unbinding Service " + c
1774                             + " that was already unbound", ex);
1775                 }
1776             }
1777             if (context == null) {
1778                 throw new IllegalStateException("Unbinding Service " + c
1779                         + " from Context that is no longer in use: " + context);
1780             } else {
1781                 throw new IllegalArgumentException("Service not registered: " + c);
1782             }
1783         }
1784     }
1785 
1786     static final class ServiceDispatcher {
1787         private final ServiceDispatcher.InnerConnection mIServiceConnection;
1788         @UnsupportedAppUsage
1789         private final ServiceConnection mConnection;
1790         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1791         private final Context mContext;
1792         private final Handler mActivityThread;
1793         private final Executor mActivityExecutor;
1794         private final ServiceConnectionLeaked mLocation;
1795         private final int mFlags;
1796 
1797         private RuntimeException mUnbindLocation;
1798 
1799         private boolean mForgotten;
1800 
1801         private static class ConnectionInfo {
1802             IBinder binder;
1803             IBinder.DeathRecipient deathMonitor;
1804         }
1805 
1806         private static class InnerConnection extends IServiceConnection.Stub {
1807             @UnsupportedAppUsage
1808             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1809 
InnerConnection(LoadedApk.ServiceDispatcher sd)1810             InnerConnection(LoadedApk.ServiceDispatcher sd) {
1811                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1812             }
1813 
connected(ComponentName name, IBinder service, boolean dead)1814             public void connected(ComponentName name, IBinder service, boolean dead)
1815                     throws RemoteException {
1816                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1817                 if (sd != null) {
1818                     sd.connected(name, service, dead);
1819                 }
1820             }
1821         }
1822 
1823         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1824             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
1825 
1826         @UnsupportedAppUsage
ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)1827         ServiceDispatcher(ServiceConnection conn,
1828                 Context context, Handler activityThread, int flags) {
1829             mIServiceConnection = new InnerConnection(this);
1830             mConnection = conn;
1831             mContext = context;
1832             mActivityThread = activityThread;
1833             mActivityExecutor = null;
1834             mLocation = new ServiceConnectionLeaked(null);
1835             mLocation.fillInStackTrace();
1836             mFlags = flags;
1837         }
1838 
ServiceDispatcher(ServiceConnection conn, Context context, Executor activityExecutor, int flags)1839         ServiceDispatcher(ServiceConnection conn,
1840                 Context context, Executor activityExecutor, int flags) {
1841             mIServiceConnection = new InnerConnection(this);
1842             mConnection = conn;
1843             mContext = context;
1844             mActivityThread = null;
1845             mActivityExecutor = activityExecutor;
1846             mLocation = new ServiceConnectionLeaked(null);
1847             mLocation.fillInStackTrace();
1848             mFlags = flags;
1849         }
1850 
validate(Context context, Handler activityThread, Executor activityExecutor)1851         void validate(Context context, Handler activityThread, Executor activityExecutor) {
1852             if (mContext != context) {
1853                 throw new RuntimeException(
1854                     "ServiceConnection " + mConnection +
1855                     " registered with differing Context (was " +
1856                     mContext + " now " + context + ")");
1857             }
1858             if (mActivityThread != activityThread) {
1859                 throw new RuntimeException(
1860                     "ServiceConnection " + mConnection +
1861                     " registered with differing handler (was " +
1862                     mActivityThread + " now " + activityThread + ")");
1863             }
1864             if (mActivityExecutor != activityExecutor) {
1865                 throw new RuntimeException(
1866                     "ServiceConnection " + mConnection +
1867                     " registered with differing executor (was " +
1868                     mActivityExecutor + " now " + activityExecutor + ")");
1869             }
1870         }
1871 
doForget()1872         void doForget() {
1873             synchronized(this) {
1874                 for (int i=0; i<mActiveConnections.size(); i++) {
1875                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
1876                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1877                 }
1878                 mActiveConnections.clear();
1879                 mForgotten = true;
1880             }
1881         }
1882 
getLocation()1883         ServiceConnectionLeaked getLocation() {
1884             return mLocation;
1885         }
1886 
getServiceConnection()1887         ServiceConnection getServiceConnection() {
1888             return mConnection;
1889         }
1890 
1891         @UnsupportedAppUsage
getIServiceConnection()1892         IServiceConnection getIServiceConnection() {
1893             return mIServiceConnection;
1894         }
1895 
getFlags()1896         int getFlags() {
1897             return mFlags;
1898         }
1899 
setUnbindLocation(RuntimeException ex)1900         void setUnbindLocation(RuntimeException ex) {
1901             mUnbindLocation = ex;
1902         }
1903 
getUnbindLocation()1904         RuntimeException getUnbindLocation() {
1905             return mUnbindLocation;
1906         }
1907 
connected(ComponentName name, IBinder service, boolean dead)1908         public void connected(ComponentName name, IBinder service, boolean dead) {
1909             if (mActivityExecutor != null) {
1910                 mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
1911             } else if (mActivityThread != null) {
1912                 mActivityThread.post(new RunConnection(name, service, 0, dead));
1913             } else {
1914                 doConnected(name, service, dead);
1915             }
1916         }
1917 
death(ComponentName name, IBinder service)1918         public void death(ComponentName name, IBinder service) {
1919             if (mActivityExecutor != null) {
1920                 mActivityExecutor.execute(new RunConnection(name, service, 1, false));
1921             } else if (mActivityThread != null) {
1922                 mActivityThread.post(new RunConnection(name, service, 1, false));
1923             } else {
1924                 doDeath(name, service);
1925             }
1926         }
1927 
doConnected(ComponentName name, IBinder service, boolean dead)1928         public void doConnected(ComponentName name, IBinder service, boolean dead) {
1929             ServiceDispatcher.ConnectionInfo old;
1930             ServiceDispatcher.ConnectionInfo info;
1931 
1932             synchronized (this) {
1933                 if (mForgotten) {
1934                     // We unbound before receiving the connection; ignore
1935                     // any connection received.
1936                     return;
1937                 }
1938                 old = mActiveConnections.get(name);
1939                 if (old != null && old.binder == service) {
1940                     // Huh, already have this one.  Oh well!
1941                     return;
1942                 }
1943 
1944                 if (service != null) {
1945                     // A new service is being connected... set it all up.
1946                     info = new ConnectionInfo();
1947                     info.binder = service;
1948                     info.deathMonitor = new DeathMonitor(name, service);
1949                     try {
1950                         service.linkToDeath(info.deathMonitor, 0);
1951                         mActiveConnections.put(name, info);
1952                     } catch (RemoteException e) {
1953                         // This service was dead before we got it...  just
1954                         // don't do anything with it.
1955                         mActiveConnections.remove(name);
1956                         return;
1957                     }
1958 
1959                 } else {
1960                     // The named service is being disconnected... clean up.
1961                     mActiveConnections.remove(name);
1962                 }
1963 
1964                 if (old != null) {
1965                     old.binder.unlinkToDeath(old.deathMonitor, 0);
1966                 }
1967             }
1968 
1969             // If there was an old service, it is now disconnected.
1970             if (old != null) {
1971                 mConnection.onServiceDisconnected(name);
1972             }
1973             if (dead) {
1974                 mConnection.onBindingDied(name);
1975             }
1976             // If there is a new viable service, it is now connected.
1977             if (service != null) {
1978                 mConnection.onServiceConnected(name, service);
1979             } else {
1980                 // The binding machinery worked, but the remote returned null from onBind().
1981                 mConnection.onNullBinding(name);
1982             }
1983         }
1984 
doDeath(ComponentName name, IBinder service)1985         public void doDeath(ComponentName name, IBinder service) {
1986             synchronized (this) {
1987                 ConnectionInfo old = mActiveConnections.get(name);
1988                 if (old == null || old.binder != service) {
1989                     // Death for someone different than who we last
1990                     // reported...  just ignore it.
1991                     return;
1992                 }
1993                 mActiveConnections.remove(name);
1994                 old.binder.unlinkToDeath(old.deathMonitor, 0);
1995             }
1996 
1997             mConnection.onServiceDisconnected(name);
1998         }
1999 
2000         private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead)2001             RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
2002                 mName = name;
2003                 mService = service;
2004                 mCommand = command;
2005                 mDead = dead;
2006             }
2007 
run()2008             public void run() {
2009                 if (mCommand == 0) {
2010                     doConnected(mName, mService, mDead);
2011                 } else if (mCommand == 1) {
2012                     doDeath(mName, mService);
2013                 }
2014             }
2015 
2016             final ComponentName mName;
2017             final IBinder mService;
2018             final int mCommand;
2019             final boolean mDead;
2020         }
2021 
2022         private final class DeathMonitor implements IBinder.DeathRecipient
2023         {
DeathMonitor(ComponentName name, IBinder service)2024             DeathMonitor(ComponentName name, IBinder service) {
2025                 mName = name;
2026                 mService = service;
2027             }
2028 
binderDied()2029             public void binderDied() {
2030                 death(mName, mService);
2031             }
2032 
2033             final ComponentName mName;
2034             final IBinder mService;
2035         }
2036     }
2037 }
2038