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