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