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