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