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