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