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.content.BroadcastReceiver;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.IIntentReceiver;
23 import android.content.Intent;
24 import android.content.ServiceConnection;
25 import android.content.pm.ApplicationInfo;
26 import android.content.pm.IPackageManager;
27 import android.content.pm.PackageManager;
28 import android.content.res.AssetManager;
29 import android.content.res.CompatibilityInfo;
30 import android.content.res.Resources;
31 import android.os.Bundle;
32 import android.os.Environment;
33 import android.os.FileUtils;
34 import android.os.Handler;
35 import android.os.IBinder;
36 import android.os.Process;
37 import android.os.RemoteException;
38 import android.os.StrictMode;
39 import android.os.SystemProperties;
40 import android.os.Trace;
41 import android.os.UserHandle;
42 import android.system.Os;
43 import android.system.OsConstants;
44 import android.system.ErrnoException;
45 import android.text.TextUtils;
46 import android.util.AndroidRuntimeException;
47 import android.util.ArrayMap;
48 import android.util.Log;
49 import android.util.Slog;
50 import android.util.SparseArray;
51 import android.view.Display;
52 import android.view.DisplayAdjustments;
53 
54 import dalvik.system.VMRuntime;
55 
56 import java.io.File;
57 import java.io.FileDescriptor;
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.lang.ref.WeakReference;
61 import java.lang.reflect.InvocationTargetException;
62 import java.lang.reflect.Method;
63 import java.net.URL;
64 import java.util.ArrayList;
65 import java.util.Collections;
66 import java.util.Enumeration;
67 import java.util.List;
68 import java.util.Objects;
69 
70 import libcore.io.IoUtils;
71 
72 final class IntentReceiverLeaked extends AndroidRuntimeException {
IntentReceiverLeaked(String msg)73     public IntentReceiverLeaked(String msg) {
74         super(msg);
75     }
76 }
77 
78 final class ServiceConnectionLeaked extends AndroidRuntimeException {
ServiceConnectionLeaked(String msg)79     public ServiceConnectionLeaked(String msg) {
80         super(msg);
81     }
82 }
83 
84 /**
85  * Local state maintained about a currently loaded .apk.
86  * @hide
87  */
88 public final class LoadedApk {
89 
90     private static final String TAG = "LoadedApk";
91 
92     private final ActivityThread mActivityThread;
93     final String mPackageName;
94     private ApplicationInfo mApplicationInfo;
95     private String mAppDir;
96     private String mResDir;
97     private String[] mSplitAppDirs;
98     private String[] mSplitResDirs;
99     private String[] mOverlayDirs;
100     private String[] mSharedLibraries;
101     private String mDataDir;
102     private String mLibDir;
103     private File mDataDirFile;
104     private File mDeviceProtectedDataDirFile;
105     private File mCredentialProtectedDataDirFile;
106     private final ClassLoader mBaseClassLoader;
107     private final boolean mSecurityViolation;
108     private final boolean mIncludeCode;
109     private final boolean mRegisterPackage;
110     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
111     /** WARNING: This may change. Don't hold external references to it. */
112     Resources mResources;
113     private ClassLoader mClassLoader;
114     private Application mApplication;
115 
116     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
117         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
118     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
119         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
120     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
121         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
122     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
123         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
124 
125     int mClientCount = 0;
126 
getApplication()127     Application getApplication() {
128         return mApplication;
129     }
130 
131     /**
132      * Create information about a new .apk
133      *
134      * NOTE: This constructor is called with ActivityThread's lock held,
135      * so MUST NOT call back out to the activity manager.
136      */
LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage)137     public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
138             CompatibilityInfo compatInfo, ClassLoader baseLoader,
139             boolean securityViolation, boolean includeCode, boolean registerPackage) {
140 
141         mActivityThread = activityThread;
142         setApplicationInfo(aInfo);
143         mPackageName = aInfo.packageName;
144         mBaseClassLoader = baseLoader;
145         mSecurityViolation = securityViolation;
146         mIncludeCode = includeCode;
147         mRegisterPackage = registerPackage;
148         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
149     }
150 
adjustNativeLibraryPaths(ApplicationInfo info)151     private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
152         // If we're dealing with a multi-arch application that has both
153         // 32 and 64 bit shared libraries, we might need to choose the secondary
154         // depending on what the current runtime's instruction set is.
155         if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
156             final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
157 
158             // Get the instruction set that the libraries of secondary Abi is supported.
159             // In presence of a native bridge this might be different than the one secondary Abi used.
160             String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
161             final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
162             secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
163 
164             // If the runtimeIsa is the same as the primary isa, then we do nothing.
165             // Everything will be set up correctly because info.nativeLibraryDir will
166             // correspond to the right ISA.
167             if (runtimeIsa.equals(secondaryIsa)) {
168                 final ApplicationInfo modified = new ApplicationInfo(info);
169                 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
170                 modified.primaryCpuAbi = modified.secondaryCpuAbi;
171                 return modified;
172             }
173         }
174 
175         return info;
176     }
177 
178     /**
179      * Create information about the system package.
180      * Must call {@link #installSystemApplicationInfo} later.
181      */
LoadedApk(ActivityThread activityThread)182     LoadedApk(ActivityThread activityThread) {
183         mActivityThread = activityThread;
184         mApplicationInfo = new ApplicationInfo();
185         mApplicationInfo.packageName = "android";
186         mPackageName = "android";
187         mAppDir = null;
188         mResDir = null;
189         mSplitAppDirs = null;
190         mSplitResDirs = null;
191         mOverlayDirs = null;
192         mSharedLibraries = null;
193         mDataDir = null;
194         mDataDirFile = null;
195         mDeviceProtectedDataDirFile = null;
196         mCredentialProtectedDataDirFile = null;
197         mLibDir = null;
198         mBaseClassLoader = null;
199         mSecurityViolation = false;
200         mIncludeCode = true;
201         mRegisterPackage = false;
202         mClassLoader = ClassLoader.getSystemClassLoader();
203         mResources = Resources.getSystem();
204     }
205 
206     /**
207      * Sets application info about the system package.
208      */
installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader)209     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
210         assert info.packageName.equals("android");
211         mApplicationInfo = info;
212         mClassLoader = classLoader;
213     }
214 
getPackageName()215     public String getPackageName() {
216         return mPackageName;
217     }
218 
getApplicationInfo()219     public ApplicationInfo getApplicationInfo() {
220         return mApplicationInfo;
221     }
222 
getTargetSdkVersion()223     public int getTargetSdkVersion() {
224         return mApplicationInfo.targetSdkVersion;
225     }
226 
isSecurityViolation()227     public boolean isSecurityViolation() {
228         return mSecurityViolation;
229     }
230 
getCompatibilityInfo()231     public CompatibilityInfo getCompatibilityInfo() {
232         return mDisplayAdjustments.getCompatibilityInfo();
233     }
234 
setCompatibilityInfo(CompatibilityInfo compatInfo)235     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
236         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
237     }
238 
239     /**
240      * Gets the array of shared libraries that are listed as
241      * used by the given package.
242      *
243      * @param packageName the name of the package (note: not its
244      * file name)
245      * @return null-ok; the array of shared libraries, each one
246      * a fully-qualified path
247      */
getLibrariesFor(String packageName)248     private static String[] getLibrariesFor(String packageName) {
249         ApplicationInfo ai = null;
250         try {
251             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
252                     PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
253         } catch (RemoteException e) {
254             throw e.rethrowFromSystemServer();
255         }
256 
257         if (ai == null) {
258             return null;
259         }
260 
261         return ai.sharedLibraryFiles;
262     }
263 
updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths)264     public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
265         setApplicationInfo(aInfo);
266 
267         final List<String> newPaths = new ArrayList<>();
268         makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
269         final List<String> addedPaths = new ArrayList<>(newPaths.size());
270 
271         if (oldPaths != null) {
272             for (String path : newPaths) {
273                 final String apkName = path.substring(path.lastIndexOf(File.separator));
274                 boolean match = false;
275                 for (String oldPath : oldPaths) {
276                     final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
277                     if (apkName.equals(oldApkName)) {
278                         match = true;
279                         break;
280                     }
281                 }
282                 if (!match) {
283                     addedPaths.add(path);
284                 }
285             }
286         } else {
287             addedPaths.addAll(newPaths);
288         }
289         synchronized (this) {
290             createOrUpdateClassLoaderLocked(addedPaths);
291             if (mResources != null) {
292                 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
293                         mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
294                         this);
295             }
296         }
297     }
298 
setApplicationInfo(ApplicationInfo aInfo)299     private void setApplicationInfo(ApplicationInfo aInfo) {
300         final int myUid = Process.myUid();
301         aInfo = adjustNativeLibraryPaths(aInfo);
302         mApplicationInfo = aInfo;
303         mAppDir = aInfo.sourceDir;
304         mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
305         mSplitAppDirs = aInfo.splitSourceDirs;
306         mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
307         mOverlayDirs = aInfo.resourceDirs;
308         mSharedLibraries = aInfo.sharedLibraryFiles;
309         mDataDir = aInfo.dataDir;
310         mLibDir = aInfo.nativeLibraryDir;
311         mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
312         mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
313         mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
314     }
315 
makePaths(ActivityThread activityThread, ApplicationInfo aInfo, List<String> outZipPaths, List<String> outLibPaths)316     public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
317             List<String> outZipPaths, List<String> outLibPaths) {
318         final String appDir = aInfo.sourceDir;
319         final String[] splitAppDirs = aInfo.splitSourceDirs;
320         final String libDir = aInfo.nativeLibraryDir;
321         final String[] sharedLibraries = aInfo.sharedLibraryFiles;
322 
323         outZipPaths.clear();
324         outZipPaths.add(appDir);
325         if (splitAppDirs != null) {
326             Collections.addAll(outZipPaths, splitAppDirs);
327         }
328 
329         if (outLibPaths != null) {
330             outLibPaths.clear();
331         }
332 
333         /*
334          * The following is a bit of a hack to inject
335          * instrumentation into the system: If the app
336          * being started matches one of the instrumentation names,
337          * then we combine both the "instrumentation" and
338          * "instrumented" app into the path, along with the
339          * concatenation of both apps' shared library lists.
340          */
341 
342         String instrumentationPackageName = activityThread.mInstrumentationPackageName;
343         String instrumentationAppDir = activityThread.mInstrumentationAppDir;
344         String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
345         String instrumentationLibDir = activityThread.mInstrumentationLibDir;
346 
347         String instrumentedAppDir = activityThread.mInstrumentedAppDir;
348         String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
349         String instrumentedLibDir = activityThread.mInstrumentedLibDir;
350         String[] instrumentationLibs = null;
351 
352         if (appDir.equals(instrumentationAppDir)
353                 || appDir.equals(instrumentedAppDir)) {
354             outZipPaths.clear();
355             outZipPaths.add(instrumentationAppDir);
356             if (instrumentationSplitAppDirs != null) {
357                 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
358             }
359             if (!instrumentationAppDir.equals(instrumentedAppDir)) {
360                 outZipPaths.add(instrumentedAppDir);
361                 if (instrumentedSplitAppDirs != null) {
362                     Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
363                 }
364             }
365 
366             if (outLibPaths != null) {
367                 outLibPaths.add(instrumentationLibDir);
368                 if (!instrumentationLibDir.equals(instrumentedLibDir)) {
369                     outLibPaths.add(instrumentedLibDir);
370                 }
371             }
372 
373             if (!instrumentedAppDir.equals(instrumentationAppDir)) {
374                 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
375             }
376         }
377 
378         if (outLibPaths != null) {
379             if (outLibPaths.isEmpty()) {
380                 outLibPaths.add(libDir);
381             }
382 
383             // Add path to libraries in apk for current abi. Do this now because more entries
384             // will be added to zipPaths that shouldn't be part of the library path.
385             if (aInfo.primaryCpuAbi != null) {
386                 // Add fake libs into the library search path if we target prior to N.
387                 if (aInfo.targetSdkVersion <= 23) {
388                     outLibPaths.add("/system/fake-libs" +
389                         (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
390                 }
391                 for (String apk : outZipPaths) {
392                     outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
393                 }
394             }
395 
396             if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
397                 // Add path to system libraries to libPaths;
398                 // Access to system libs should be limited
399                 // to bundled applications; this is why updated
400                 // system apps are not included.
401                 outLibPaths.add(System.getProperty("java.library.path"));
402             }
403         }
404 
405         if (sharedLibraries != null) {
406             for (String lib : sharedLibraries) {
407                 if (!outZipPaths.contains(lib)) {
408                     outZipPaths.add(0, lib);
409                 }
410             }
411         }
412 
413         if (instrumentationLibs != null) {
414             for (String lib : instrumentationLibs) {
415                 if (!outZipPaths.contains(lib)) {
416                     outZipPaths.add(0, lib);
417                 }
418             }
419         }
420     }
421 
createOrUpdateClassLoaderLocked(List<String> addedPaths)422     private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
423         if (mPackageName.equals("android")) {
424             // Note: This branch is taken for system server and we don't need to setup
425             // jit profiling support.
426             if (mClassLoader != null) {
427                 // nothing to update
428                 return;
429             }
430 
431             if (mBaseClassLoader != null) {
432                 mClassLoader = mBaseClassLoader;
433             } else {
434                 mClassLoader = ClassLoader.getSystemClassLoader();
435             }
436 
437             return;
438         }
439 
440         // Avoid the binder call when the package is the current application package.
441         // The activity manager will perform ensure that dexopt is performed before
442         // spinning up the process.
443         if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
444             VMRuntime.getRuntime().vmInstructionSet();
445             try {
446                 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
447                         PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
448             } catch (RemoteException re) {
449                 throw re.rethrowFromSystemServer();
450             }
451         }
452 
453         if (mRegisterPackage) {
454             try {
455                 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
456             } catch (RemoteException e) {
457                 throw e.rethrowFromSystemServer();
458             }
459         }
460 
461         // Lists for the elements of zip/code and native libraries.
462         //
463         // Both lists are usually not empty. We expect on average one APK for the zip component,
464         // but shared libraries and splits are not uncommon. We expect at least three elements
465         // for native libraries (app-based, system, vendor). As such, give both some breathing
466         // space and initialize to a small value (instead of incurring growth code).
467         final List<String> zipPaths = new ArrayList<>(10);
468         final List<String> libPaths = new ArrayList<>(10);
469         makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
470 
471         final boolean isBundledApp = mApplicationInfo.isSystemApp()
472                 && !mApplicationInfo.isUpdatedSystemApp();
473 
474         String libraryPermittedPath = mDataDir;
475         if (isBundledApp) {
476             // This is necessary to grant bundled apps access to
477             // libraries located in subdirectories of /system/lib
478             libraryPermittedPath += File.pathSeparator +
479                                     System.getProperty("java.library.path");
480         }
481 
482         final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
483 
484         // If we're not asked to include code, we construct a classloader that has
485         // no code path included. We still need to set up the library search paths
486         // and permitted path because NativeActivity relies on it (it attempts to
487         // call System.loadLibrary() on a classloader from a LoadedApk with
488         // mIncludeCode == false).
489         if (!mIncludeCode) {
490             if (mClassLoader == null) {
491                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
492                 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
493                     "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
494                     librarySearchPath, libraryPermittedPath, mBaseClassLoader);
495                 StrictMode.setThreadPolicy(oldPolicy);
496             }
497 
498             return;
499         }
500 
501         /*
502          * With all the combination done (if necessary, actually create the java class
503          * loader and set up JIT profiling support if necessary.
504          *
505          * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
506          */
507         final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
508                 TextUtils.join(File.pathSeparator, zipPaths);
509 
510         if (ActivityThread.localLOGV)
511             Slog.v(ActivityThread.TAG, "Class path: " + zip +
512                     ", JNI path: " + librarySearchPath);
513 
514         boolean needToSetupJitProfiles = false;
515         if (mClassLoader == null) {
516             // Temporarily disable logging of disk reads on the Looper thread
517             // as this is early and necessary.
518             StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
519 
520             mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
521                     mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
522                     libraryPermittedPath, mBaseClassLoader);
523 
524             StrictMode.setThreadPolicy(oldPolicy);
525             // Setup the class loader paths for profiling.
526             needToSetupJitProfiles = true;
527         }
528 
529         if (addedPaths != null && addedPaths.size() > 0) {
530             final String add = TextUtils.join(File.pathSeparator, addedPaths);
531             ApplicationLoaders.getDefault().addPath(mClassLoader, add);
532             // Setup the new code paths for profiling.
533             needToSetupJitProfiles = true;
534         }
535 
536         // Setup jit profile support.
537         //
538         // It is ok to call this multiple times if the application gets updated with new splits.
539         // The runtime only keeps track of unique code paths and can handle re-registration of
540         // the same code path. There's no need to pass `addedPaths` since any new code paths
541         // are already in `mApplicationInfo`.
542         //
543         // It is NOT ok to call this function from the system_server (for any of the packages it
544         // loads code from) so we explicitly disallow it there.
545         if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
546             setupJitProfileSupport();
547         }
548     }
549 
getClassLoader()550     public ClassLoader getClassLoader() {
551         synchronized (this) {
552             if (mClassLoader == null) {
553                 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
554             }
555             return mClassLoader;
556         }
557     }
558 
559     // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
getPrimaryProfileFile(String packageName)560     private static File getPrimaryProfileFile(String packageName) {
561         File profileDir = Environment.getDataProfilesDePackageDirectory(
562                 UserHandle.myUserId(), packageName);
563         return new File(profileDir, "primary.prof");
564     }
565 
setupJitProfileSupport()566     private void setupJitProfileSupport() {
567         if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
568             return;
569         }
570         // Only set up profile support if the loaded apk has the same uid as the
571         // current process.
572         // Currently, we do not support profiling across different apps.
573         // (e.g. application's uid might be different when the code is
574         // loaded by another app via createApplicationContext)
575         if (mApplicationInfo.uid != Process.myUid()) {
576             return;
577         }
578 
579         final List<String> codePaths = new ArrayList<>();
580         if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
581             codePaths.add(mApplicationInfo.sourceDir);
582         }
583         if (mApplicationInfo.splitSourceDirs != null) {
584             Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
585         }
586 
587         if (codePaths.isEmpty()) {
588             // If there are no code paths there's no need to setup a profile file and register with
589             // the runtime,
590             return;
591         }
592 
593         final File profileFile = getPrimaryProfileFile(mPackageName);
594         final File foreignDexProfilesFile =
595                 Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
596 
597         VMRuntime.registerAppInfo(profileFile.getPath(), mApplicationInfo.dataDir,
598                 codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesFile.getPath());
599     }
600 
601     /**
602      * Setup value for Thread.getContextClassLoader(). If the
603      * package will not run in in a VM with other packages, we set
604      * the Java context ClassLoader to the
605      * PackageInfo.getClassLoader value. However, if this VM can
606      * contain multiple packages, we intead set the Java context
607      * ClassLoader to a proxy that will warn about the use of Java
608      * context ClassLoaders and then fall through to use the
609      * system ClassLoader.
610      *
611      * <p> Note that this is similar to but not the same as the
612      * android.content.Context.getClassLoader(). While both
613      * context class loaders are typically set to the
614      * PathClassLoader used to load the package archive in the
615      * single application per VM case, a single Android process
616      * may contain several Contexts executing on one thread with
617      * their own logical ClassLoaders while the Java context
618      * ClassLoader is a thread local. This is why in the case when
619      * we have multiple packages per VM we do not set the Java
620      * context ClassLoader to an arbitrary but instead warn the
621      * user to set their own if we detect that they are using a
622      * Java library that expects it to be set.
623      */
initializeJavaContextClassLoader()624     private void initializeJavaContextClassLoader() {
625         IPackageManager pm = ActivityThread.getPackageManager();
626         android.content.pm.PackageInfo pi;
627         try {
628             pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
629                     UserHandle.myUserId());
630         } catch (RemoteException e) {
631             throw e.rethrowFromSystemServer();
632         }
633         if (pi == null) {
634             throw new IllegalStateException("Unable to get package info for "
635                     + mPackageName + "; is package not installed?");
636         }
637         /*
638          * Two possible indications that this package could be
639          * sharing its virtual machine with other packages:
640          *
641          * 1.) the sharedUserId attribute is set in the manifest,
642          *     indicating a request to share a VM with other
643          *     packages with the same sharedUserId.
644          *
645          * 2.) the application element of the manifest has an
646          *     attribute specifying a non-default process name,
647          *     indicating the desire to run in another packages VM.
648          */
649         boolean sharedUserIdSet = (pi.sharedUserId != null);
650         boolean processNameNotDefault =
651             (pi.applicationInfo != null &&
652              !mPackageName.equals(pi.applicationInfo.processName));
653         boolean sharable = (sharedUserIdSet || processNameNotDefault);
654         ClassLoader contextClassLoader =
655             (sharable)
656             ? new WarningContextClassLoader()
657             : mClassLoader;
658         Thread.currentThread().setContextClassLoader(contextClassLoader);
659     }
660 
661     private static class WarningContextClassLoader extends ClassLoader {
662 
663         private static boolean warned = false;
664 
warn(String methodName)665         private void warn(String methodName) {
666             if (warned) {
667                 return;
668             }
669             warned = true;
670             Thread.currentThread().setContextClassLoader(getParent());
671             Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
672                   "The class loader returned by " +
673                   "Thread.getContextClassLoader() may fail for processes " +
674                   "that host multiple applications. You should explicitly " +
675                   "specify a context class loader. For example: " +
676                   "Thread.setContextClassLoader(getClass().getClassLoader());");
677         }
678 
getResource(String resName)679         @Override public URL getResource(String resName) {
680             warn("getResource");
681             return getParent().getResource(resName);
682         }
683 
getResources(String resName)684         @Override public Enumeration<URL> getResources(String resName) throws IOException {
685             warn("getResources");
686             return getParent().getResources(resName);
687         }
688 
getResourceAsStream(String resName)689         @Override public InputStream getResourceAsStream(String resName) {
690             warn("getResourceAsStream");
691             return getParent().getResourceAsStream(resName);
692         }
693 
loadClass(String className)694         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
695             warn("loadClass");
696             return getParent().loadClass(className);
697         }
698 
setClassAssertionStatus(String cname, boolean enable)699         @Override public void setClassAssertionStatus(String cname, boolean enable) {
700             warn("setClassAssertionStatus");
701             getParent().setClassAssertionStatus(cname, enable);
702         }
703 
setPackageAssertionStatus(String pname, boolean enable)704         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
705             warn("setPackageAssertionStatus");
706             getParent().setPackageAssertionStatus(pname, enable);
707         }
708 
setDefaultAssertionStatus(boolean enable)709         @Override public void setDefaultAssertionStatus(boolean enable) {
710             warn("setDefaultAssertionStatus");
711             getParent().setDefaultAssertionStatus(enable);
712         }
713 
clearAssertionStatus()714         @Override public void clearAssertionStatus() {
715             warn("clearAssertionStatus");
716             getParent().clearAssertionStatus();
717         }
718     }
719 
getAppDir()720     public String getAppDir() {
721         return mAppDir;
722     }
723 
getLibDir()724     public String getLibDir() {
725         return mLibDir;
726     }
727 
getResDir()728     public String getResDir() {
729         return mResDir;
730     }
731 
getSplitAppDirs()732     public String[] getSplitAppDirs() {
733         return mSplitAppDirs;
734     }
735 
getSplitResDirs()736     public String[] getSplitResDirs() {
737         return mSplitResDirs;
738     }
739 
getOverlayDirs()740     public String[] getOverlayDirs() {
741         return mOverlayDirs;
742     }
743 
getDataDir()744     public String getDataDir() {
745         return mDataDir;
746     }
747 
getDataDirFile()748     public File getDataDirFile() {
749         return mDataDirFile;
750     }
751 
getDeviceProtectedDataDirFile()752     public File getDeviceProtectedDataDirFile() {
753         return mDeviceProtectedDataDirFile;
754     }
755 
getCredentialProtectedDataDirFile()756     public File getCredentialProtectedDataDirFile() {
757         return mCredentialProtectedDataDirFile;
758     }
759 
getAssets(ActivityThread mainThread)760     public AssetManager getAssets(ActivityThread mainThread) {
761         return getResources(mainThread).getAssets();
762     }
763 
getResources(ActivityThread mainThread)764     public Resources getResources(ActivityThread mainThread) {
765         if (mResources == null) {
766             mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
767                     mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
768         }
769         return mResources;
770     }
771 
makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation)772     public Application makeApplication(boolean forceDefaultAppClass,
773             Instrumentation instrumentation) {
774         if (mApplication != null) {
775             return mApplication;
776         }
777 
778         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
779 
780         Application app = null;
781 
782         String appClass = mApplicationInfo.className;
783         if (forceDefaultAppClass || (appClass == null)) {
784             appClass = "android.app.Application";
785         }
786 
787         try {
788             java.lang.ClassLoader cl = getClassLoader();
789             if (!mPackageName.equals("android")) {
790                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
791                         "initializeJavaContextClassLoader");
792                 initializeJavaContextClassLoader();
793                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
794             }
795             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
796             app = mActivityThread.mInstrumentation.newApplication(
797                     cl, appClass, appContext);
798             appContext.setOuterContext(app);
799         } catch (Exception e) {
800             if (!mActivityThread.mInstrumentation.onException(app, e)) {
801                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
802                 throw new RuntimeException(
803                     "Unable to instantiate application " + appClass
804                     + ": " + e.toString(), e);
805             }
806         }
807         mActivityThread.mAllApplications.add(app);
808         mApplication = app;
809 
810         if (instrumentation != null) {
811             try {
812                 instrumentation.callApplicationOnCreate(app);
813             } catch (Exception e) {
814                 if (!instrumentation.onException(app, e)) {
815                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
816                     throw new RuntimeException(
817                         "Unable to create application " + app.getClass().getName()
818                         + ": " + e.toString(), e);
819                 }
820             }
821         }
822 
823         // Rewrite the R 'constants' for all library apks.
824         SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
825                 .getAssignedPackageIdentifiers();
826         final int N = packageIdentifiers.size();
827         for (int i = 0; i < N; i++) {
828             final int id = packageIdentifiers.keyAt(i);
829             if (id == 0x01 || id == 0x7f) {
830                 continue;
831             }
832 
833             rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
834         }
835 
836         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
837 
838         return app;
839     }
840 
rewriteRValues(ClassLoader cl, String packageName, int id)841     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
842         final Class<?> rClazz;
843         try {
844             rClazz = cl.loadClass(packageName + ".R");
845         } catch (ClassNotFoundException e) {
846             // This is not necessarily an error, as some packages do not ship with resources
847             // (or they do not need rewriting).
848             Log.i(TAG, "No resource references to update in package " + packageName);
849             return;
850         }
851 
852         final Method callback;
853         try {
854             callback = rClazz.getMethod("onResourcesLoaded", int.class);
855         } catch (NoSuchMethodException e) {
856             // No rewriting to be done.
857             return;
858         }
859 
860         Throwable cause;
861         try {
862             callback.invoke(null, id);
863             return;
864         } catch (IllegalAccessException e) {
865             cause = e;
866         } catch (InvocationTargetException e) {
867             cause = e.getCause();
868         }
869 
870         throw new RuntimeException("Failed to rewrite resource references for " + packageName,
871                 cause);
872     }
873 
removeContextRegistrations(Context context, String who, String what)874     public void removeContextRegistrations(Context context,
875             String who, String what) {
876         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
877         synchronized (mReceivers) {
878             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
879                     mReceivers.remove(context);
880             if (rmap != null) {
881                 for (int i = 0; i < rmap.size(); i++) {
882                     LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
883                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
884                             what + " " + who + " has leaked IntentReceiver "
885                             + rd.getIntentReceiver() + " that was " +
886                             "originally registered here. Are you missing a " +
887                             "call to unregisterReceiver()?");
888                     leak.setStackTrace(rd.getLocation().getStackTrace());
889                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
890                     if (reportRegistrationLeaks) {
891                         StrictMode.onIntentReceiverLeaked(leak);
892                     }
893                     try {
894                         ActivityManagerNative.getDefault().unregisterReceiver(
895                                 rd.getIIntentReceiver());
896                     } catch (RemoteException e) {
897                         throw e.rethrowFromSystemServer();
898                     }
899                 }
900             }
901             mUnregisteredReceivers.remove(context);
902         }
903 
904         synchronized (mServices) {
905             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
906             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
907                     mServices.remove(context);
908             if (smap != null) {
909                 for (int i = 0; i < smap.size(); i++) {
910                     LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
911                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
912                             what + " " + who + " has leaked ServiceConnection "
913                             + sd.getServiceConnection() + " that was originally bound here");
914                     leak.setStackTrace(sd.getLocation().getStackTrace());
915                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
916                     if (reportRegistrationLeaks) {
917                         StrictMode.onServiceConnectionLeaked(leak);
918                     }
919                     try {
920                         ActivityManagerNative.getDefault().unbindService(
921                                 sd.getIServiceConnection());
922                     } catch (RemoteException e) {
923                         throw e.rethrowFromSystemServer();
924                     }
925                     sd.doForget();
926                 }
927             }
928             mUnboundServices.remove(context);
929             //Slog.i(TAG, "Service registrations: " + mServices);
930         }
931     }
932 
getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)933     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
934             Context context, Handler handler,
935             Instrumentation instrumentation, boolean registered) {
936         synchronized (mReceivers) {
937             LoadedApk.ReceiverDispatcher rd = null;
938             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
939             if (registered) {
940                 map = mReceivers.get(context);
941                 if (map != null) {
942                     rd = map.get(r);
943                 }
944             }
945             if (rd == null) {
946                 rd = new ReceiverDispatcher(r, context, handler,
947                         instrumentation, registered);
948                 if (registered) {
949                     if (map == null) {
950                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
951                         mReceivers.put(context, map);
952                     }
953                     map.put(r, rd);
954                 }
955             } else {
956                 rd.validate(context, handler);
957             }
958             rd.mForgotten = false;
959             return rd.getIIntentReceiver();
960         }
961     }
962 
forgetReceiverDispatcher(Context context, BroadcastReceiver r)963     public IIntentReceiver forgetReceiverDispatcher(Context context,
964             BroadcastReceiver r) {
965         synchronized (mReceivers) {
966             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
967             LoadedApk.ReceiverDispatcher rd = null;
968             if (map != null) {
969                 rd = map.get(r);
970                 if (rd != null) {
971                     map.remove(r);
972                     if (map.size() == 0) {
973                         mReceivers.remove(context);
974                     }
975                     if (r.getDebugUnregister()) {
976                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
977                                 = mUnregisteredReceivers.get(context);
978                         if (holder == null) {
979                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
980                             mUnregisteredReceivers.put(context, holder);
981                         }
982                         RuntimeException ex = new IllegalArgumentException(
983                                 "Originally unregistered here:");
984                         ex.fillInStackTrace();
985                         rd.setUnregisterLocation(ex);
986                         holder.put(r, rd);
987                     }
988                     rd.mForgotten = true;
989                     return rd.getIIntentReceiver();
990                 }
991             }
992             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
993                     = mUnregisteredReceivers.get(context);
994             if (holder != null) {
995                 rd = holder.get(r);
996                 if (rd != null) {
997                     RuntimeException ex = rd.getUnregisterLocation();
998                     throw new IllegalArgumentException(
999                             "Unregistering Receiver " + r
1000                             + " that was already unregistered", ex);
1001                 }
1002             }
1003             if (context == null) {
1004                 throw new IllegalStateException("Unbinding Receiver " + r
1005                         + " from Context that is no longer in use: " + context);
1006             } else {
1007                 throw new IllegalArgumentException("Receiver not registered: " + r);
1008             }
1009 
1010         }
1011     }
1012 
1013     static final class ReceiverDispatcher {
1014 
1015         final static class InnerReceiver extends IIntentReceiver.Stub {
1016             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1017             final LoadedApk.ReceiverDispatcher mStrongRef;
1018 
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)1019             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1020                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1021                 mStrongRef = strong ? rd : null;
1022             }
1023 
1024             @Override
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1025             public void performReceive(Intent intent, int resultCode, String data,
1026                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1027                 final LoadedApk.ReceiverDispatcher rd;
1028                 if (intent == null) {
1029                     Log.wtf(TAG, "Null intent received");
1030                     rd = null;
1031                 } else {
1032                     rd = mDispatcher.get();
1033                 }
1034                 if (ActivityThread.DEBUG_BROADCAST) {
1035                     int seq = intent.getIntExtra("seq", -1);
1036                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1037                             + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
1038                 }
1039                 if (rd != null) {
1040                     rd.performReceive(intent, resultCode, data, extras,
1041                             ordered, sticky, sendingUser);
1042                 } else {
1043                     // The activity manager dispatched a broadcast to a registered
1044                     // receiver in this process, but before it could be delivered the
1045                     // receiver was unregistered.  Acknowledge the broadcast on its
1046                     // behalf so that the system's broadcast sequence can continue.
1047                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1048                             "Finishing broadcast to unregistered receiver");
1049                     IActivityManager mgr = ActivityManagerNative.getDefault();
1050                     try {
1051                         if (extras != null) {
1052                             extras.setAllowFds(false);
1053                         }
1054                         mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
1055                     } catch (RemoteException e) {
1056                         throw e.rethrowFromSystemServer();
1057                     }
1058                 }
1059             }
1060         }
1061 
1062         final IIntentReceiver.Stub mIIntentReceiver;
1063         final BroadcastReceiver mReceiver;
1064         final Context mContext;
1065         final Handler mActivityThread;
1066         final Instrumentation mInstrumentation;
1067         final boolean mRegistered;
1068         final IntentReceiverLeaked mLocation;
1069         RuntimeException mUnregisterLocation;
1070         boolean mForgotten;
1071 
1072         final class Args extends BroadcastReceiver.PendingResult implements Runnable {
1073             private Intent mCurIntent;
1074             private final boolean mOrdered;
1075             private boolean mDispatched;
1076 
Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)1077             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
1078                     boolean ordered, boolean sticky, int sendingUser) {
1079                 super(resultCode, resultData, resultExtras,
1080                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1081                         sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
1082                 mCurIntent = intent;
1083                 mOrdered = ordered;
1084             }
1085 
run()1086             public void run() {
1087                 final BroadcastReceiver receiver = mReceiver;
1088                 final boolean ordered = mOrdered;
1089 
1090                 if (ActivityThread.DEBUG_BROADCAST) {
1091                     int seq = mCurIntent.getIntExtra("seq", -1);
1092                     Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1093                             + " seq=" + seq + " to " + mReceiver);
1094                     Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
1095                             + " mOrderedHint=" + ordered);
1096                 }
1097 
1098                 final IActivityManager mgr = ActivityManagerNative.getDefault();
1099                 final Intent intent = mCurIntent;
1100                 if (intent == null) {
1101                     Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
1102                 }
1103 
1104                 mCurIntent = null;
1105                 mDispatched = true;
1106                 if (receiver == null || intent == null || mForgotten) {
1107                     if (mRegistered && ordered) {
1108                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1109                                 "Finishing null broadcast to " + mReceiver);
1110                         sendFinished(mgr);
1111                     }
1112                     return;
1113                 }
1114 
1115                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
1116                 try {
1117                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
1118                     intent.setExtrasClassLoader(cl);
1119                     intent.prepareToEnterProcess();
1120                     setExtrasClassLoader(cl);
1121                     receiver.setPendingResult(this);
1122                     receiver.onReceive(mContext, intent);
1123                 } catch (Exception e) {
1124                     if (mRegistered && ordered) {
1125                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1126                                 "Finishing failed broadcast to " + mReceiver);
1127                         sendFinished(mgr);
1128                     }
1129                     if (mInstrumentation == null ||
1130                             !mInstrumentation.onException(mReceiver, e)) {
1131                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1132                         throw new RuntimeException(
1133                             "Error receiving broadcast " + intent
1134                             + " in " + mReceiver, e);
1135                     }
1136                 }
1137 
1138                 if (receiver.getPendingResult() != null) {
1139                     finish();
1140                 }
1141                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1142             }
1143         }
1144 
ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)1145         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1146                 Handler activityThread, Instrumentation instrumentation,
1147                 boolean registered) {
1148             if (activityThread == null) {
1149                 throw new NullPointerException("Handler must not be null");
1150             }
1151 
1152             mIIntentReceiver = new InnerReceiver(this, !registered);
1153             mReceiver = receiver;
1154             mContext = context;
1155             mActivityThread = activityThread;
1156             mInstrumentation = instrumentation;
1157             mRegistered = registered;
1158             mLocation = new IntentReceiverLeaked(null);
1159             mLocation.fillInStackTrace();
1160         }
1161 
validate(Context context, Handler activityThread)1162         void validate(Context context, Handler activityThread) {
1163             if (mContext != context) {
1164                 throw new IllegalStateException(
1165                     "Receiver " + mReceiver +
1166                     " registered with differing Context (was " +
1167                     mContext + " now " + context + ")");
1168             }
1169             if (mActivityThread != activityThread) {
1170                 throw new IllegalStateException(
1171                     "Receiver " + mReceiver +
1172                     " registered with differing handler (was " +
1173                     mActivityThread + " now " + activityThread + ")");
1174             }
1175         }
1176 
getLocation()1177         IntentReceiverLeaked getLocation() {
1178             return mLocation;
1179         }
1180 
getIntentReceiver()1181         BroadcastReceiver getIntentReceiver() {
1182             return mReceiver;
1183         }
1184 
getIIntentReceiver()1185         IIntentReceiver getIIntentReceiver() {
1186             return mIIntentReceiver;
1187         }
1188 
setUnregisterLocation(RuntimeException ex)1189         void setUnregisterLocation(RuntimeException ex) {
1190             mUnregisterLocation = ex;
1191         }
1192 
getUnregisterLocation()1193         RuntimeException getUnregisterLocation() {
1194             return mUnregisterLocation;
1195         }
1196 
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1197         public void performReceive(Intent intent, int resultCode, String data,
1198                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1199             final Args args = new Args(intent, resultCode, data, extras, ordered,
1200                     sticky, sendingUser);
1201             if (intent == null) {
1202                 Log.wtf(TAG, "Null intent received");
1203             } else {
1204                 if (ActivityThread.DEBUG_BROADCAST) {
1205                     int seq = intent.getIntExtra("seq", -1);
1206                     Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1207                             + " seq=" + seq + " to " + mReceiver);
1208                 }
1209             }
1210             if (intent == null || !mActivityThread.post(args)) {
1211                 if (mRegistered && ordered) {
1212                     IActivityManager mgr = ActivityManagerNative.getDefault();
1213                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1214                             "Finishing sync broadcast to " + mReceiver);
1215                     args.sendFinished(mgr);
1216                 }
1217             }
1218         }
1219 
1220     }
1221 
getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)1222     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1223             Context context, Handler handler, int flags) {
1224         synchronized (mServices) {
1225             LoadedApk.ServiceDispatcher sd = null;
1226             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
1227             if (map != null) {
1228                 sd = map.get(c);
1229             }
1230             if (sd == null) {
1231                 sd = new ServiceDispatcher(c, context, handler, flags);
1232                 if (map == null) {
1233                     map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
1234                     mServices.put(context, map);
1235                 }
1236                 map.put(c, sd);
1237             } else {
1238                 sd.validate(context, handler);
1239             }
1240             return sd.getIServiceConnection();
1241         }
1242     }
1243 
forgetServiceDispatcher(Context context, ServiceConnection c)1244     public final IServiceConnection forgetServiceDispatcher(Context context,
1245             ServiceConnection c) {
1246         synchronized (mServices) {
1247             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
1248                     = mServices.get(context);
1249             LoadedApk.ServiceDispatcher sd = null;
1250             if (map != null) {
1251                 sd = map.get(c);
1252                 if (sd != null) {
1253                     map.remove(c);
1254                     sd.doForget();
1255                     if (map.size() == 0) {
1256                         mServices.remove(context);
1257                     }
1258                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1259                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1260                                 = mUnboundServices.get(context);
1261                         if (holder == null) {
1262                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
1263                             mUnboundServices.put(context, holder);
1264                         }
1265                         RuntimeException ex = new IllegalArgumentException(
1266                                 "Originally unbound here:");
1267                         ex.fillInStackTrace();
1268                         sd.setUnbindLocation(ex);
1269                         holder.put(c, sd);
1270                     }
1271                     return sd.getIServiceConnection();
1272                 }
1273             }
1274             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1275                     = mUnboundServices.get(context);
1276             if (holder != null) {
1277                 sd = holder.get(c);
1278                 if (sd != null) {
1279                     RuntimeException ex = sd.getUnbindLocation();
1280                     throw new IllegalArgumentException(
1281                             "Unbinding Service " + c
1282                             + " that was already unbound", ex);
1283                 }
1284             }
1285             if (context == null) {
1286                 throw new IllegalStateException("Unbinding Service " + c
1287                         + " from Context that is no longer in use: " + context);
1288             } else {
1289                 throw new IllegalArgumentException("Service not registered: " + c);
1290             }
1291         }
1292     }
1293 
1294     static final class ServiceDispatcher {
1295         private final ServiceDispatcher.InnerConnection mIServiceConnection;
1296         private final ServiceConnection mConnection;
1297         private final Context mContext;
1298         private final Handler mActivityThread;
1299         private final ServiceConnectionLeaked mLocation;
1300         private final int mFlags;
1301 
1302         private RuntimeException mUnbindLocation;
1303 
1304         private boolean mForgotten;
1305 
1306         private static class ConnectionInfo {
1307             IBinder binder;
1308             IBinder.DeathRecipient deathMonitor;
1309         }
1310 
1311         private static class InnerConnection extends IServiceConnection.Stub {
1312             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1313 
InnerConnection(LoadedApk.ServiceDispatcher sd)1314             InnerConnection(LoadedApk.ServiceDispatcher sd) {
1315                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1316             }
1317 
connected(ComponentName name, IBinder service)1318             public void connected(ComponentName name, IBinder service) throws RemoteException {
1319                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1320                 if (sd != null) {
1321                     sd.connected(name, service);
1322                 }
1323             }
1324         }
1325 
1326         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1327             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
1328 
ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)1329         ServiceDispatcher(ServiceConnection conn,
1330                 Context context, Handler activityThread, int flags) {
1331             mIServiceConnection = new InnerConnection(this);
1332             mConnection = conn;
1333             mContext = context;
1334             mActivityThread = activityThread;
1335             mLocation = new ServiceConnectionLeaked(null);
1336             mLocation.fillInStackTrace();
1337             mFlags = flags;
1338         }
1339 
validate(Context context, Handler activityThread)1340         void validate(Context context, Handler activityThread) {
1341             if (mContext != context) {
1342                 throw new RuntimeException(
1343                     "ServiceConnection " + mConnection +
1344                     " registered with differing Context (was " +
1345                     mContext + " now " + context + ")");
1346             }
1347             if (mActivityThread != activityThread) {
1348                 throw new RuntimeException(
1349                     "ServiceConnection " + mConnection +
1350                     " registered with differing handler (was " +
1351                     mActivityThread + " now " + activityThread + ")");
1352             }
1353         }
1354 
doForget()1355         void doForget() {
1356             synchronized(this) {
1357                 for (int i=0; i<mActiveConnections.size(); i++) {
1358                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
1359                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1360                 }
1361                 mActiveConnections.clear();
1362                 mForgotten = true;
1363             }
1364         }
1365 
getLocation()1366         ServiceConnectionLeaked getLocation() {
1367             return mLocation;
1368         }
1369 
getServiceConnection()1370         ServiceConnection getServiceConnection() {
1371             return mConnection;
1372         }
1373 
getIServiceConnection()1374         IServiceConnection getIServiceConnection() {
1375             return mIServiceConnection;
1376         }
1377 
getFlags()1378         int getFlags() {
1379             return mFlags;
1380         }
1381 
setUnbindLocation(RuntimeException ex)1382         void setUnbindLocation(RuntimeException ex) {
1383             mUnbindLocation = ex;
1384         }
1385 
getUnbindLocation()1386         RuntimeException getUnbindLocation() {
1387             return mUnbindLocation;
1388         }
1389 
connected(ComponentName name, IBinder service)1390         public void connected(ComponentName name, IBinder service) {
1391             if (mActivityThread != null) {
1392                 mActivityThread.post(new RunConnection(name, service, 0));
1393             } else {
1394                 doConnected(name, service);
1395             }
1396         }
1397 
death(ComponentName name, IBinder service)1398         public void death(ComponentName name, IBinder service) {
1399             ServiceDispatcher.ConnectionInfo old;
1400 
1401             synchronized (this) {
1402                 old = mActiveConnections.remove(name);
1403                 if (old == null || old.binder != service) {
1404                     // Death for someone different than who we last
1405                     // reported...  just ignore it.
1406                     return;
1407                 }
1408                 old.binder.unlinkToDeath(old.deathMonitor, 0);
1409             }
1410 
1411             if (mActivityThread != null) {
1412                 mActivityThread.post(new RunConnection(name, service, 1));
1413             } else {
1414                 doDeath(name, service);
1415             }
1416         }
1417 
doConnected(ComponentName name, IBinder service)1418         public void doConnected(ComponentName name, IBinder service) {
1419             ServiceDispatcher.ConnectionInfo old;
1420             ServiceDispatcher.ConnectionInfo info;
1421 
1422             synchronized (this) {
1423                 if (mForgotten) {
1424                     // We unbound before receiving the connection; ignore
1425                     // any connection received.
1426                     return;
1427                 }
1428                 old = mActiveConnections.get(name);
1429                 if (old != null && old.binder == service) {
1430                     // Huh, already have this one.  Oh well!
1431                     return;
1432                 }
1433 
1434                 if (service != null) {
1435                     // A new service is being connected... set it all up.
1436                     info = new ConnectionInfo();
1437                     info.binder = service;
1438                     info.deathMonitor = new DeathMonitor(name, service);
1439                     try {
1440                         service.linkToDeath(info.deathMonitor, 0);
1441                         mActiveConnections.put(name, info);
1442                     } catch (RemoteException e) {
1443                         // This service was dead before we got it...  just
1444                         // don't do anything with it.
1445                         mActiveConnections.remove(name);
1446                         return;
1447                     }
1448 
1449                 } else {
1450                     // The named service is being disconnected... clean up.
1451                     mActiveConnections.remove(name);
1452                 }
1453 
1454                 if (old != null) {
1455                     old.binder.unlinkToDeath(old.deathMonitor, 0);
1456                 }
1457             }
1458 
1459             // If there was an old service, it is not disconnected.
1460             if (old != null) {
1461                 mConnection.onServiceDisconnected(name);
1462             }
1463             // If there is a new service, it is now connected.
1464             if (service != null) {
1465                 mConnection.onServiceConnected(name, service);
1466             }
1467         }
1468 
doDeath(ComponentName name, IBinder service)1469         public void doDeath(ComponentName name, IBinder service) {
1470             mConnection.onServiceDisconnected(name);
1471         }
1472 
1473         private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command)1474             RunConnection(ComponentName name, IBinder service, int command) {
1475                 mName = name;
1476                 mService = service;
1477                 mCommand = command;
1478             }
1479 
run()1480             public void run() {
1481                 if (mCommand == 0) {
1482                     doConnected(mName, mService);
1483                 } else if (mCommand == 1) {
1484                     doDeath(mName, mService);
1485                 }
1486             }
1487 
1488             final ComponentName mName;
1489             final IBinder mService;
1490             final int mCommand;
1491         }
1492 
1493         private final class DeathMonitor implements IBinder.DeathRecipient
1494         {
DeathMonitor(ComponentName name, IBinder service)1495             DeathMonitor(ComponentName name, IBinder service) {
1496                 mName = name;
1497                 mService = service;
1498             }
1499 
binderDied()1500             public void binderDied() {
1501                 death(mName, mService);
1502             }
1503 
1504             final ComponentName mName;
1505             final IBinder mService;
1506         }
1507     }
1508 }
1509