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