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