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