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