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