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