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