Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8498cd0 authored by Todd Kennedy's avatar Todd Kennedy Committed by Android (Google) Code Review
Browse files

Merge "Splits without restart" into nyc-dev

parents adef8317 39bfee5e
Loading
Loading
Loading
Loading
+86 −14
Original line number Diff line number Diff line
@@ -1788,7 +1788,8 @@ public final class ActivityThread {
    }

    /**
     * Creates the top level resources for the given package.
     * Creates the top level resources for the given package. Will return an existing
     * Resources if one has already been created.
     */
    Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
            String[] libDirs, int displayId, Configuration overrideConfiguration,
@@ -1798,6 +1799,19 @@ public final class ActivityThread {
                pkgInfo.getClassLoader());
    }

    /**
     * Creates a new top level resources for the given package. Will always create a new
     * Resources, regardless if one has already been created.
     */
    Resources getNewTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
            String[] libDirs, int displayId, Configuration overrideConfiguration,
            LoadedApk pkgInfo) {
        mResourcesManager.removeTopLevelResources(
                resDir, displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
        return getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
                displayId, overrideConfiguration, pkgInfo);
    }

    final Handler getHandler() {
        return mH;
    }
@@ -4749,13 +4763,18 @@ public final class ActivityThread {

    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
        boolean hasPkgInfo = false;
        if (packages != null) {
        switch (cmd) {
            case IApplicationThread.PACKAGE_REMOVED:
            case IApplicationThread.PACKAGE_REMOVED_DONT_KILL:
            {
                final boolean killApp = cmd == IApplicationThread.PACKAGE_REMOVED;
                if (packages == null) {
                    break;
                }
                synchronized (mResourcesManager) {
                    for (int i = packages.length - 1; i >= 0; i--) {
                    //Slog.i(TAG, "Cleaning old package: " + packages[i]);
                        if (!hasPkgInfo) {
                        WeakReference<LoadedApk> ref;
                        ref = mPackages.get(packages[i]);
                            WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
                            if (ref != null && ref.get() != null) {
                                hasPkgInfo = true;
                            } else {
@@ -4765,13 +4784,66 @@ public final class ActivityThread {
                                }
                            }
                        }
                        if (killApp) {
                            mPackages.remove(packages[i]);
                            mResourcePackages.remove(packages[i]);
                        }
                    }
                }
        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
                hasPkgInfo);
                break;
            }
            case IApplicationThread.PACKAGE_REPLACED:
            {
                if (packages == null) {
                    break;
                }
                synchronized (mResourcesManager) {
                    for (int i = packages.length - 1; i >= 0; i--) {
                        WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
                        LoadedApk pkgInfo = ref != null ? ref.get() : null;
                        if (pkgInfo != null) {
                            hasPkgInfo = true;
                        } else {
                            ref = mResourcePackages.get(packages[i]);
                            pkgInfo = ref != null ? ref.get() : null;
                            if (pkgInfo != null) {
                                hasPkgInfo = true;
                            }
                        }
                        // If the package is being replaced, yet it still has a valid
                        // LoadedApk object, the package was updated with _DONT_KILL.
                        // Adjust it's internal references to the application info and
                        // resources.
                        if (pkgInfo != null) {
                            try {
                                final String packageName = packages[i];
                                final ApplicationInfo aInfo =
                                        sPackageManager.getApplicationInfo(
                                                packageName,
                                                0 /*flags*/,
                                                UserHandle.myUserId());

                                if (mActivities.size() > 0) {
                                    for (ActivityClientRecord ar : mActivities.values()) {
                                        if (ar.activityInfo.applicationInfo.packageName
                                                .equals(packageName)) {
                                            ar.activityInfo.applicationInfo = aInfo;
                                            ar.packageInfo = pkgInfo;
                                        }
                                    }
                                }
                                final List<String> oldPaths =
                                        sPackageManager.getPreviousCodePaths(packageName);
                                pkgInfo.updateApplicationInfo(aInfo, oldPaths);
                            } catch (RemoteException e) {
                            }
                        }
                    }
                }
                break;
            }
        }
        ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
    }

    final void handleLowMemory() {
+12 −0
Original line number Diff line number Diff line
@@ -86,6 +86,18 @@ class ApplicationLoaders {
                                                            String libraryPermittedPath,
                                                            boolean isShared);

    /**
     * Adds a new path the classpath of the given loader.
     * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
     */
    void addPath(ClassLoader classLoader, String dexPath) {
        if (!(classLoader instanceof PathClassLoader)) {
            throw new IllegalStateException("class loader is not a PathClassLoader");
        }
        final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
        baseDexClassLoader.addDexPath(dexPath);
    }

    private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<String, ClassLoader>();

    private static final ApplicationLoaders gApplicationLoaders
+5 −0
Original line number Diff line number Diff line
@@ -123,8 +123,13 @@ public interface IApplicationThread extends IInterface {
    void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
            throws RemoteException;
    void setSchedulingGroup(int group) throws RemoteException;
    // the package has been removed, clean up internal references
    static final int PACKAGE_REMOVED = 0;
    static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
    // the package is being modified in-place, don't kill it and retain references to it
    static final int PACKAGE_REMOVED_DONT_KILL = 2;
    // a previously removed package was replaced with a new version [eg. upgrade, split added, ...]
    static final int PACKAGE_REPLACED = 3;
    void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
    void scheduleCrash(String msg) throws RemoteException;
    void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
+203 −131
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Objects;
@@ -83,24 +84,25 @@ public final class LoadedApk {
    private static final String TAG = "LoadedApk";

    private final ActivityThread mActivityThread;
    private ApplicationInfo mApplicationInfo;
    final String mPackageName;
    private final String mAppDir;
    private final String mResDir;
    private final String[] mSplitAppDirs;
    private final String[] mSplitResDirs;
    private final String[] mOverlayDirs;
    private final String[] mSharedLibraries;
    private final String mDataDir;
    private final String mLibDir;
    private final File mDataDirFile;
    private final File mDeviceEncryptedDataDirFile;
    private final File mCredentialEncryptedDataDirFile;
    private ApplicationInfo mApplicationInfo;
    private String mAppDir;
    private String mResDir;
    private String[] mSplitAppDirs;
    private String[] mSplitResDirs;
    private String[] mOverlayDirs;
    private String[] mSharedLibraries;
    private String mDataDir;
    private String mLibDir;
    private File mDataDirFile;
    private File mDeviceEncryptedDataDirFile;
    private File mCredentialEncryptedDataDirFile;
    private final ClassLoader mBaseClassLoader;
    private final boolean mSecurityViolation;
    private final boolean mIncludeCode;
    private final boolean mRegisterPackage;
    private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
    /** WARNING: This may change. Don't hold external references to it. */
    Resources mResources;
    private ClassLoader mClassLoader;
    private Application mApplication;
@@ -129,23 +131,10 @@ public final class LoadedApk {
    public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
            CompatibilityInfo compatInfo, ClassLoader baseLoader,
            boolean securityViolation, boolean includeCode, boolean registerPackage) {
        final int myUid = Process.myUid();
        aInfo = adjustNativeLibraryPaths(aInfo);

        mActivityThread = activityThread;
        mApplicationInfo = aInfo;
        setApplicationInfo(aInfo);
        mPackageName = aInfo.packageName;
        mAppDir = aInfo.sourceDir;
        mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
        mSplitAppDirs = aInfo.splitSourceDirs;
        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
        mOverlayDirs = aInfo.resourceDirs;
        mSharedLibraries = aInfo.sharedLibraryFiles;
        mDataDir = aInfo.dataDir;
        mDataDirFile = FileUtils.newFileOrNull(mDataDir);
        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
        mLibDir = aInfo.nativeLibraryDir;
        mBaseClassLoader = baseLoader;
        mSecurityViolation = securityViolation;
        mIncludeCode = includeCode;
@@ -266,51 +255,74 @@ public final class LoadedApk {
        return ai.sharedLibraryFiles;
    }

    public ClassLoader getClassLoader() {
        synchronized (this) {
            if (mClassLoader != null) {
                return mClassLoader;
            }
    public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
        setApplicationInfo(aInfo);

            if (mPackageName.equals("android")) {
                if (mBaseClassLoader == null) {
                    mClassLoader = ClassLoader.getSystemClassLoader();
        final List<String> newPaths = new ArrayList<>();
        makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
        final List<String> addedPaths = new ArrayList<>(newPaths.size());

        if (oldPaths != null) {
            for (String path : newPaths) {
                final String apkName = path.substring(path.lastIndexOf(File.separator));
                boolean match = false;
                for (String oldPath : oldPaths) {
                    final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
                    if (apkName.equals(oldApkName)) {
                        match = true;
                        break;
                    }
                }
                if (!match) {
                    addedPaths.add(path);
                }
            }
        } else {
                    mClassLoader = mBaseClassLoader;
            addedPaths.addAll(newPaths);
        }
                return mClassLoader;
        synchronized (this) {
            mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
            if (mResources != null) {
                mResources = mActivityThread.getNewTopLevelResources(mResDir, mSplitResDirs,
                        mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
                        null /*overrideConfiguration*/, this);
            }

            // Avoid the binder call when the package is the current application package.
            // The activity manager will perform ensure that dexopt is performed before
            // spinning up the process.
            if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
                final String isa = VMRuntime.getRuntime().vmInstructionSet();
                try {
                    ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
                } catch (RemoteException re) {
                    throw re.rethrowFromSystemServer();
        }
    }

            final List<String> zipPaths = new ArrayList<>();
            final List<String> apkPaths = new ArrayList<>();
            final List<String> libPaths = new ArrayList<>();

            if (mRegisterPackage) {
                try {
                    ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
    private void setApplicationInfo(ApplicationInfo aInfo) {
        final int myUid = Process.myUid();
        aInfo = adjustNativeLibraryPaths(aInfo);
        mApplicationInfo = aInfo;
        mAppDir = aInfo.sourceDir;
        mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
        mSplitAppDirs = aInfo.splitSourceDirs;
        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
        mOverlayDirs = aInfo.resourceDirs;
        mSharedLibraries = aInfo.sharedLibraryFiles;
        mDataDir = aInfo.dataDir;
        mLibDir = aInfo.nativeLibraryDir;
        mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
    }

            zipPaths.add(mAppDir);
            if (mSplitAppDirs != null) {
                Collections.addAll(zipPaths, mSplitAppDirs);
    public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
            List<String> outZipPaths, List<String> outLibPaths) {
        final String appDir = aInfo.sourceDir;
        final String[] splitAppDirs = aInfo.splitSourceDirs;
        final String libDir = aInfo.nativeLibraryDir;
        final String[] sharedLibraries = aInfo.sharedLibraryFiles;

        outZipPaths.clear();
        outZipPaths.add(appDir);
        if (splitAppDirs != null) {
            Collections.addAll(outZipPaths, splitAppDirs);
        }

            libPaths.add(mLibDir);
        if (outLibPaths != null) {
            outLibPaths.clear();
        }

        /*
         * The following is a bit of a hack to inject
@@ -321,75 +333,111 @@ public final class LoadedApk {
         * concatenation of both apps' shared library lists.
         */

            String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
            String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
            String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
            String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
        String instrumentationPackageName = activityThread.mInstrumentationPackageName;
        String instrumentationAppDir = activityThread.mInstrumentationAppDir;
        String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
        String instrumentationLibDir = activityThread.mInstrumentationLibDir;

            String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
            String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
            String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
        String instrumentedAppDir = activityThread.mInstrumentedAppDir;
        String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
        String instrumentedLibDir = activityThread.mInstrumentedLibDir;
        String[] instrumentationLibs = null;

            if (mAppDir.equals(instrumentationAppDir)
                    || mAppDir.equals(instrumentedAppDir)) {
                zipPaths.clear();
                zipPaths.add(instrumentationAppDir);
        if (appDir.equals(instrumentationAppDir)
                || appDir.equals(instrumentedAppDir)) {
            outZipPaths.clear();
            outZipPaths.add(instrumentationAppDir);
            if (instrumentationSplitAppDirs != null) {
                    Collections.addAll(zipPaths, instrumentationSplitAppDirs);
                Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
            }
                zipPaths.add(instrumentedAppDir);
            outZipPaths.add(instrumentedAppDir);
            if (instrumentedSplitAppDirs != null) {
                    Collections.addAll(zipPaths, instrumentedSplitAppDirs);
                Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
            }

                libPaths.clear();
                libPaths.add(instrumentationLibDir);
                libPaths.add(instrumentedLibDir);
            if (outLibPaths != null) {
                outLibPaths.add(instrumentationLibDir);
                outLibPaths.add(instrumentedLibDir);
            }

            if (!instrumentedAppDir.equals(instrumentationAppDir)) {
                instrumentationLibs = getLibrariesFor(instrumentationPackageName);
            }
        }

            apkPaths.addAll(zipPaths);
        if (outLibPaths != null) {
            if (outLibPaths.isEmpty()) {
                outLibPaths.add(libDir);
            }

            // Add path to libraries in apk for current abi. Do this now because more entries
            // will be added to zipPaths that shouldn't be part of the library path.
            if (aInfo.primaryCpuAbi != null) {
                for (String apk : outZipPaths) {
                    outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
                }
            }

            if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
                // Add path to system libraries to libPaths;
                // Access to system libs should be limited
                // to bundled applications; this is why updated
                // system apps are not included.
                outLibPaths.add(System.getProperty("java.library.path"));
            }
        }

            if (mSharedLibraries != null) {
                for (String lib : mSharedLibraries) {
                    if (!zipPaths.contains(lib)) {
                        zipPaths.add(0, lib);
        if (sharedLibraries != null) {
            for (String lib : sharedLibraries) {
                if (!outZipPaths.contains(lib)) {
                    outZipPaths.add(0, lib);
                }
            }
        }

        if (instrumentationLibs != null) {
            for (String lib : instrumentationLibs) {
                    if (!zipPaths.contains(lib)) {
                        zipPaths.add(0, lib);
                if (!outZipPaths.contains(lib)) {
                    outZipPaths.add(0, lib);
                }
            }
        }

            final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
        final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
    }

            // Add path to libraries in apk for current abi
            if (mApplicationInfo.primaryCpuAbi != null) {
                for (String apk : apkPaths) {
                  libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
    private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
        final ClassLoader classLoader;
        if (mIncludeCode && !mPackageName.equals("android")) {
            // Avoid the binder call when the package is the current application package.
            // The activity manager will perform ensure that dexopt is performed before
            // spinning up the process.
            if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
                VMRuntime.getRuntime().vmInstructionSet();
                try {
                    ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
                } catch (RemoteException re) {
                    throw re.rethrowFromSystemServer();
                }
            }

            String libraryPermittedPath = mDataDir;
            boolean isBundledApp = false;
            final List<String> zipPaths = new ArrayList<>();
            final List<String> libPaths = new ArrayList<>();

            if (mApplicationInfo.isSystemApp() && !mApplicationInfo.isUpdatedSystemApp()) {
                isBundledApp = true;
                // Add path to system libraries to libPaths;
                // Access to system libs should be limited
                // to bundled applications; this is why updated
                // system apps are not included.
                libPaths.add(System.getProperty("java.library.path"));
            if (mRegisterPackage) {
                try {
                    ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }

            makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
            final String zip = TextUtils.join(File.pathSeparator, zipPaths);
            final boolean isBundledApp = mApplicationInfo.isSystemApp()
                    && !mApplicationInfo.isUpdatedSystemApp();
            String libraryPermittedPath = mDataDir;
            if (isBundledApp) {
                // This is necessary to grant bundled apps access to
                // libraries located in subdirectories of /system/lib
                libraryPermittedPath += File.pathSeparator +
@@ -414,15 +462,42 @@ public final class LoadedApk {
                Slog.v(ActivityThread.TAG, "Class path: " + zip +
                        ", JNI path: " + librarySearchPath);

            if (mClassLoader == null) {
                // Temporarily disable logging of disk reads on the Looper thread
                // as this is early and necessary.
                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();

            mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
                classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
                        mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                        libraryPermittedPath, mBaseClassLoader);

                StrictMode.setThreadPolicy(oldPolicy);
            } else if (addedPaths != null && addedPaths.size() > 0) {
                final String add = TextUtils.join(File.pathSeparator, addedPaths);
                ApplicationLoaders.getDefault().addPath(mClassLoader, add);
                classLoader = mClassLoader;
            } else {
                classLoader = mClassLoader;
            }
        } else {
            if (mClassLoader == null) {
                if (mBaseClassLoader == null) {
                    classLoader = ClassLoader.getSystemClassLoader();
                } else {
                    classLoader = mBaseClassLoader;
                }
            } else {
                classLoader = mClassLoader;
            }
        }
        return classLoader;
    }

    public ClassLoader getClassLoader() {
        synchronized (this) {
            if (mClassLoader == null) {
                mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
            }
            return mClassLoader;
        }
    }
@@ -1103,7 +1178,6 @@ public final class LoadedApk {

        private RuntimeException mUnbindLocation;

        private boolean mDied;
        private boolean mForgotten;

        private static class ConnectionInfo {
@@ -1202,7 +1276,6 @@ public final class LoadedApk {
            ServiceDispatcher.ConnectionInfo old;

            synchronized (this) {
                mDied = true;
                old = mActiveConnections.remove(name);
                if (old == null || old.binder != service) {
                    // Death for someone different than who we last
@@ -1237,7 +1310,6 @@ public final class LoadedApk {

                if (service != null) {
                    // A new service is being connected... set it all up.
                    mDied = false;
                    info = new ConnectionInfo();
                    info.binder = service;
                    info.deathMonitor = new DeathMonitor(name, service);
+13 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading