• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.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         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
636                 mReceivers.remove(context);
637         if (rmap != null) {
638             for (int i=0; i<rmap.size(); i++) {
639                 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
640                 IntentReceiverLeaked leak = new IntentReceiverLeaked(
641                         what + " " + who + " has leaked IntentReceiver "
642                         + rd.getIntentReceiver() + " that was " +
643                         "originally registered here. Are you missing a " +
644                         "call to unregisterReceiver()?");
645                 leak.setStackTrace(rd.getLocation().getStackTrace());
646                 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
647                 if (reportRegistrationLeaks) {
648                     StrictMode.onIntentReceiverLeaked(leak);
649                 }
650                 try {
651                     ActivityManagerNative.getDefault().unregisterReceiver(
652                             rd.getIIntentReceiver());
653                 } catch (RemoteException e) {
654                     // system crashed, nothing we can do
655                 }
656             }
657         }
658         mUnregisteredReceivers.remove(context);
659         //Slog.i(TAG, "Receiver registrations: " + mReceivers);
660         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
661             mServices.remove(context);
662         if (smap != null) {
663             for (int i=0; i<smap.size(); i++) {
664                 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
665                 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
666                         what + " " + who + " has leaked ServiceConnection "
667                         + sd.getServiceConnection() + " that was originally bound here");
668                 leak.setStackTrace(sd.getLocation().getStackTrace());
669                 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
670                 if (reportRegistrationLeaks) {
671                     StrictMode.onServiceConnectionLeaked(leak);
672                 }
673                 try {
674                     ActivityManagerNative.getDefault().unbindService(
675                             sd.getIServiceConnection());
676                 } catch (RemoteException e) {
677                     // system crashed, nothing we can do
678                 }
679                 sd.doForget();
680             }
681         }
682         mUnboundServices.remove(context);
683         //Slog.i(TAG, "Service registrations: " + mServices);
684     }
685 
getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)686     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
687             Context context, Handler handler,
688             Instrumentation instrumentation, boolean registered) {
689         synchronized (mReceivers) {
690             LoadedApk.ReceiverDispatcher rd = null;
691             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
692             if (registered) {
693                 map = mReceivers.get(context);
694                 if (map != null) {
695                     rd = map.get(r);
696                 }
697             }
698             if (rd == null) {
699                 rd = new ReceiverDispatcher(r, context, handler,
700                         instrumentation, registered);
701                 if (registered) {
702                     if (map == null) {
703                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
704                         mReceivers.put(context, map);
705                     }
706                     map.put(r, rd);
707                 }
708             } else {
709                 rd.validate(context, handler);
710             }
711             rd.mForgotten = false;
712             return rd.getIIntentReceiver();
713         }
714     }
715 
forgetReceiverDispatcher(Context context, BroadcastReceiver r)716     public IIntentReceiver forgetReceiverDispatcher(Context context,
717             BroadcastReceiver r) {
718         synchronized (mReceivers) {
719             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
720             LoadedApk.ReceiverDispatcher rd = null;
721             if (map != null) {
722                 rd = map.get(r);
723                 if (rd != null) {
724                     map.remove(r);
725                     if (map.size() == 0) {
726                         mReceivers.remove(context);
727                     }
728                     if (r.getDebugUnregister()) {
729                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
730                                 = mUnregisteredReceivers.get(context);
731                         if (holder == null) {
732                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
733                             mUnregisteredReceivers.put(context, holder);
734                         }
735                         RuntimeException ex = new IllegalArgumentException(
736                                 "Originally unregistered here:");
737                         ex.fillInStackTrace();
738                         rd.setUnregisterLocation(ex);
739                         holder.put(r, rd);
740                     }
741                     rd.mForgotten = true;
742                     return rd.getIIntentReceiver();
743                 }
744             }
745             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
746                     = mUnregisteredReceivers.get(context);
747             if (holder != null) {
748                 rd = holder.get(r);
749                 if (rd != null) {
750                     RuntimeException ex = rd.getUnregisterLocation();
751                     throw new IllegalArgumentException(
752                             "Unregistering Receiver " + r
753                             + " that was already unregistered", ex);
754                 }
755             }
756             if (context == null) {
757                 throw new IllegalStateException("Unbinding Receiver " + r
758                         + " from Context that is no longer in use: " + context);
759             } else {
760                 throw new IllegalArgumentException("Receiver not registered: " + r);
761             }
762 
763         }
764     }
765 
766     static final class ReceiverDispatcher {
767 
768         final static class InnerReceiver extends IIntentReceiver.Stub {
769             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
770             final LoadedApk.ReceiverDispatcher mStrongRef;
771 
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)772             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
773                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
774                 mStrongRef = strong ? rd : null;
775             }
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)776             public void performReceive(Intent intent, int resultCode, String data,
777                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
778                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
779                 if (ActivityThread.DEBUG_BROADCAST) {
780                     int seq = intent.getIntExtra("seq", -1);
781                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
782                             + " to " + (rd != null ? rd.mReceiver : null));
783                 }
784                 if (rd != null) {
785                     rd.performReceive(intent, resultCode, data, extras,
786                             ordered, sticky, sendingUser);
787                 } else {
788                     // The activity manager dispatched a broadcast to a registered
789                     // receiver in this process, but before it could be delivered the
790                     // receiver was unregistered.  Acknowledge the broadcast on its
791                     // behalf so that the system's broadcast sequence can continue.
792                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
793                             "Finishing broadcast to unregistered receiver");
794                     IActivityManager mgr = ActivityManagerNative.getDefault();
795                     try {
796                         if (extras != null) {
797                             extras.setAllowFds(false);
798                         }
799                         mgr.finishReceiver(this, resultCode, data, extras, false);
800                     } catch (RemoteException e) {
801                         Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
802                     }
803                 }
804             }
805         }
806 
807         final IIntentReceiver.Stub mIIntentReceiver;
808         final BroadcastReceiver mReceiver;
809         final Context mContext;
810         final Handler mActivityThread;
811         final Instrumentation mInstrumentation;
812         final boolean mRegistered;
813         final IntentReceiverLeaked mLocation;
814         RuntimeException mUnregisterLocation;
815         boolean mForgotten;
816 
817         final class Args extends BroadcastReceiver.PendingResult implements Runnable {
818             private Intent mCurIntent;
819             private final boolean mOrdered;
820 
Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)821             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
822                     boolean ordered, boolean sticky, int sendingUser) {
823                 super(resultCode, resultData, resultExtras,
824                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
825                         ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
826                 mCurIntent = intent;
827                 mOrdered = ordered;
828             }
829 
run()830             public void run() {
831                 final BroadcastReceiver receiver = mReceiver;
832                 final boolean ordered = mOrdered;
833 
834                 if (ActivityThread.DEBUG_BROADCAST) {
835                     int seq = mCurIntent.getIntExtra("seq", -1);
836                     Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
837                             + " seq=" + seq + " to " + mReceiver);
838                     Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
839                             + " mOrderedHint=" + ordered);
840                 }
841 
842                 final IActivityManager mgr = ActivityManagerNative.getDefault();
843                 final Intent intent = mCurIntent;
844                 mCurIntent = null;
845 
846                 if (receiver == null || mForgotten) {
847                     if (mRegistered && ordered) {
848                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
849                                 "Finishing null broadcast to " + mReceiver);
850                         sendFinished(mgr);
851                     }
852                     return;
853                 }
854 
855                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
856                 try {
857                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
858                     intent.setExtrasClassLoader(cl);
859                     setExtrasClassLoader(cl);
860                     receiver.setPendingResult(this);
861                     receiver.onReceive(mContext, intent);
862                 } catch (Exception e) {
863                     if (mRegistered && ordered) {
864                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
865                                 "Finishing failed broadcast to " + mReceiver);
866                         sendFinished(mgr);
867                     }
868                     if (mInstrumentation == null ||
869                             !mInstrumentation.onException(mReceiver, e)) {
870                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
871                         throw new RuntimeException(
872                             "Error receiving broadcast " + intent
873                             + " in " + mReceiver, e);
874                     }
875                 }
876 
877                 if (receiver.getPendingResult() != null) {
878                     finish();
879                 }
880                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
881             }
882         }
883 
ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)884         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
885                 Handler activityThread, Instrumentation instrumentation,
886                 boolean registered) {
887             if (activityThread == null) {
888                 throw new NullPointerException("Handler must not be null");
889             }
890 
891             mIIntentReceiver = new InnerReceiver(this, !registered);
892             mReceiver = receiver;
893             mContext = context;
894             mActivityThread = activityThread;
895             mInstrumentation = instrumentation;
896             mRegistered = registered;
897             mLocation = new IntentReceiverLeaked(null);
898             mLocation.fillInStackTrace();
899         }
900 
validate(Context context, Handler activityThread)901         void validate(Context context, Handler activityThread) {
902             if (mContext != context) {
903                 throw new IllegalStateException(
904                     "Receiver " + mReceiver +
905                     " registered with differing Context (was " +
906                     mContext + " now " + context + ")");
907             }
908             if (mActivityThread != activityThread) {
909                 throw new IllegalStateException(
910                     "Receiver " + mReceiver +
911                     " registered with differing handler (was " +
912                     mActivityThread + " now " + activityThread + ")");
913             }
914         }
915 
getLocation()916         IntentReceiverLeaked getLocation() {
917             return mLocation;
918         }
919 
getIntentReceiver()920         BroadcastReceiver getIntentReceiver() {
921             return mReceiver;
922         }
923 
getIIntentReceiver()924         IIntentReceiver getIIntentReceiver() {
925             return mIIntentReceiver;
926         }
927 
setUnregisterLocation(RuntimeException ex)928         void setUnregisterLocation(RuntimeException ex) {
929             mUnregisterLocation = ex;
930         }
931 
getUnregisterLocation()932         RuntimeException getUnregisterLocation() {
933             return mUnregisterLocation;
934         }
935 
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)936         public void performReceive(Intent intent, int resultCode, String data,
937                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
938             if (ActivityThread.DEBUG_BROADCAST) {
939                 int seq = intent.getIntExtra("seq", -1);
940                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
941                         + " to " + mReceiver);
942             }
943             Args args = new Args(intent, resultCode, data, extras, ordered,
944                     sticky, sendingUser);
945             if (!mActivityThread.post(args)) {
946                 if (mRegistered && ordered) {
947                     IActivityManager mgr = ActivityManagerNative.getDefault();
948                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
949                             "Finishing sync broadcast to " + mReceiver);
950                     args.sendFinished(mgr);
951                 }
952             }
953         }
954 
955     }
956 
getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)957     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
958             Context context, Handler handler, int flags) {
959         synchronized (mServices) {
960             LoadedApk.ServiceDispatcher sd = null;
961             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
962             if (map != null) {
963                 sd = map.get(c);
964             }
965             if (sd == null) {
966                 sd = new ServiceDispatcher(c, context, handler, flags);
967                 if (map == null) {
968                     map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
969                     mServices.put(context, map);
970                 }
971                 map.put(c, sd);
972             } else {
973                 sd.validate(context, handler);
974             }
975             return sd.getIServiceConnection();
976         }
977     }
978 
forgetServiceDispatcher(Context context, ServiceConnection c)979     public final IServiceConnection forgetServiceDispatcher(Context context,
980             ServiceConnection c) {
981         synchronized (mServices) {
982             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
983                     = mServices.get(context);
984             LoadedApk.ServiceDispatcher sd = null;
985             if (map != null) {
986                 sd = map.get(c);
987                 if (sd != null) {
988                     map.remove(c);
989                     sd.doForget();
990                     if (map.size() == 0) {
991                         mServices.remove(context);
992                     }
993                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
994                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
995                                 = mUnboundServices.get(context);
996                         if (holder == null) {
997                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
998                             mUnboundServices.put(context, holder);
999                         }
1000                         RuntimeException ex = new IllegalArgumentException(
1001                                 "Originally unbound here:");
1002                         ex.fillInStackTrace();
1003                         sd.setUnbindLocation(ex);
1004                         holder.put(c, sd);
1005                     }
1006                     return sd.getIServiceConnection();
1007                 }
1008             }
1009             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1010                     = mUnboundServices.get(context);
1011             if (holder != null) {
1012                 sd = holder.get(c);
1013                 if (sd != null) {
1014                     RuntimeException ex = sd.getUnbindLocation();
1015                     throw new IllegalArgumentException(
1016                             "Unbinding Service " + c
1017                             + " that was already unbound", ex);
1018                 }
1019             }
1020             if (context == null) {
1021                 throw new IllegalStateException("Unbinding Service " + c
1022                         + " from Context that is no longer in use: " + context);
1023             } else {
1024                 throw new IllegalArgumentException("Service not registered: " + c);
1025             }
1026         }
1027     }
1028 
1029     static final class ServiceDispatcher {
1030         private final ServiceDispatcher.InnerConnection mIServiceConnection;
1031         private final ServiceConnection mConnection;
1032         private final Context mContext;
1033         private final Handler mActivityThread;
1034         private final ServiceConnectionLeaked mLocation;
1035         private final int mFlags;
1036 
1037         private RuntimeException mUnbindLocation;
1038 
1039         private boolean mDied;
1040         private boolean mForgotten;
1041 
1042         private static class ConnectionInfo {
1043             IBinder binder;
1044             IBinder.DeathRecipient deathMonitor;
1045         }
1046 
1047         private static class InnerConnection extends IServiceConnection.Stub {
1048             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1049 
InnerConnection(LoadedApk.ServiceDispatcher sd)1050             InnerConnection(LoadedApk.ServiceDispatcher sd) {
1051                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1052             }
1053 
connected(ComponentName name, IBinder service)1054             public void connected(ComponentName name, IBinder service) throws RemoteException {
1055                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1056                 if (sd != null) {
1057                     sd.connected(name, service);
1058                 }
1059             }
1060         }
1061 
1062         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1063             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
1064 
ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)1065         ServiceDispatcher(ServiceConnection conn,
1066                 Context context, Handler activityThread, int flags) {
1067             mIServiceConnection = new InnerConnection(this);
1068             mConnection = conn;
1069             mContext = context;
1070             mActivityThread = activityThread;
1071             mLocation = new ServiceConnectionLeaked(null);
1072             mLocation.fillInStackTrace();
1073             mFlags = flags;
1074         }
1075 
validate(Context context, Handler activityThread)1076         void validate(Context context, Handler activityThread) {
1077             if (mContext != context) {
1078                 throw new RuntimeException(
1079                     "ServiceConnection " + mConnection +
1080                     " registered with differing Context (was " +
1081                     mContext + " now " + context + ")");
1082             }
1083             if (mActivityThread != activityThread) {
1084                 throw new RuntimeException(
1085                     "ServiceConnection " + mConnection +
1086                     " registered with differing handler (was " +
1087                     mActivityThread + " now " + activityThread + ")");
1088             }
1089         }
1090 
doForget()1091         void doForget() {
1092             synchronized(this) {
1093                 for (int i=0; i<mActiveConnections.size(); i++) {
1094                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
1095                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1096                 }
1097                 mActiveConnections.clear();
1098                 mForgotten = true;
1099             }
1100         }
1101 
getLocation()1102         ServiceConnectionLeaked getLocation() {
1103             return mLocation;
1104         }
1105 
getServiceConnection()1106         ServiceConnection getServiceConnection() {
1107             return mConnection;
1108         }
1109 
getIServiceConnection()1110         IServiceConnection getIServiceConnection() {
1111             return mIServiceConnection;
1112         }
1113 
getFlags()1114         int getFlags() {
1115             return mFlags;
1116         }
1117 
setUnbindLocation(RuntimeException ex)1118         void setUnbindLocation(RuntimeException ex) {
1119             mUnbindLocation = ex;
1120         }
1121 
getUnbindLocation()1122         RuntimeException getUnbindLocation() {
1123             return mUnbindLocation;
1124         }
1125 
connected(ComponentName name, IBinder service)1126         public void connected(ComponentName name, IBinder service) {
1127             if (mActivityThread != null) {
1128                 mActivityThread.post(new RunConnection(name, service, 0));
1129             } else {
1130                 doConnected(name, service);
1131             }
1132         }
1133 
death(ComponentName name, IBinder service)1134         public void death(ComponentName name, IBinder service) {
1135             ServiceDispatcher.ConnectionInfo old;
1136 
1137             synchronized (this) {
1138                 mDied = true;
1139                 old = mActiveConnections.remove(name);
1140                 if (old == null || old.binder != service) {
1141                     // Death for someone different than who we last
1142                     // reported...  just ignore it.
1143                     return;
1144                 }
1145                 old.binder.unlinkToDeath(old.deathMonitor, 0);
1146             }
1147 
1148             if (mActivityThread != null) {
1149                 mActivityThread.post(new RunConnection(name, service, 1));
1150             } else {
1151                 doDeath(name, service);
1152             }
1153         }
1154 
doConnected(ComponentName name, IBinder service)1155         public void doConnected(ComponentName name, IBinder service) {
1156             ServiceDispatcher.ConnectionInfo old;
1157             ServiceDispatcher.ConnectionInfo info;
1158 
1159             synchronized (this) {
1160                 if (mForgotten) {
1161                     // We unbound before receiving the connection; ignore
1162                     // any connection received.
1163                     return;
1164                 }
1165                 old = mActiveConnections.get(name);
1166                 if (old != null && old.binder == service) {
1167                     // Huh, already have this one.  Oh well!
1168                     return;
1169                 }
1170 
1171                 if (service != null) {
1172                     // A new service is being connected... set it all up.
1173                     mDied = false;
1174                     info = new ConnectionInfo();
1175                     info.binder = service;
1176                     info.deathMonitor = new DeathMonitor(name, service);
1177                     try {
1178                         service.linkToDeath(info.deathMonitor, 0);
1179                         mActiveConnections.put(name, info);
1180                     } catch (RemoteException e) {
1181                         // This service was dead before we got it...  just
1182                         // don't do anything with it.
1183                         mActiveConnections.remove(name);
1184                         return;
1185                     }
1186 
1187                 } else {
1188                     // The named service is being disconnected... clean up.
1189                     mActiveConnections.remove(name);
1190                 }
1191 
1192                 if (old != null) {
1193                     old.binder.unlinkToDeath(old.deathMonitor, 0);
1194                 }
1195             }
1196 
1197             // If there was an old service, it is not disconnected.
1198             if (old != null) {
1199                 mConnection.onServiceDisconnected(name);
1200             }
1201             // If there is a new service, it is now connected.
1202             if (service != null) {
1203                 mConnection.onServiceConnected(name, service);
1204             }
1205         }
1206 
doDeath(ComponentName name, IBinder service)1207         public void doDeath(ComponentName name, IBinder service) {
1208             mConnection.onServiceDisconnected(name);
1209         }
1210 
1211         private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command)1212             RunConnection(ComponentName name, IBinder service, int command) {
1213                 mName = name;
1214                 mService = service;
1215                 mCommand = command;
1216             }
1217 
run()1218             public void run() {
1219                 if (mCommand == 0) {
1220                     doConnected(mName, mService);
1221                 } else if (mCommand == 1) {
1222                     doDeath(mName, mService);
1223                 }
1224             }
1225 
1226             final ComponentName mName;
1227             final IBinder mService;
1228             final int mCommand;
1229         }
1230 
1231         private final class DeathMonitor implements IBinder.DeathRecipient
1232         {
DeathMonitor(ComponentName name, IBinder service)1233             DeathMonitor(ComponentName name, IBinder service) {
1234                 mName = name;
1235                 mService = service;
1236             }
1237 
binderDied()1238             public void binderDied() {
1239                 death(mName, mService);
1240             }
1241 
1242             final ComponentName mName;
1243             final IBinder mService;
1244         }
1245     }
1246 }
1247