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

Commit 486d760e authored by Ricky Wai's avatar Ricky Wai
Browse files

Pass bind mount storage data decision from java to zygote

Before we used store dirty data in system property to record
if FUSE for a user is mounted, and zygote uses it to determine
if storage mount is needed. It introduces performance issues and
not reliable.

This CL does the following changes:

- System server determines if storage dirs mount are needed, and store
the record inside system server.

- It passes the verdict to zygote so zygote just need to follow the
input.

- When emulated storage is mounted / unmounted, it will record if
FUSE for that user is ready to use, and will be used for determining
if storage dirs mount are needed when a new process starts.

- After emulated storage is mounted, it will create an async thread
to remount all storage dirs for existing app processes. As we have a
record of pids that storage dirs are not mounted yet, we can use it
directly without scanning the whole /proc in vold.

Bug: 149548518
Test: After flag is enabled, AdoptableHostTest still pass.
Change-Id: Ic99d027d42b2b9a1c7fd03070b36c44882c6e7c5
parent a8375cc9
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.TransactionTooLargeException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Activity manager local system service interface.
@@ -123,6 +124,12 @@ public abstract class ActivityManagerInternal {
     */
    public abstract int getUidProcessState(int uid);

    /**
     * Get a map of pid and package name that process of that pid Android/data and Android/obb
     * directory is not mounted to lowerfs.
     */
    public abstract Map<Integer, String> getProcessesWithPendingBindMounts(int userId);

    /**
     * @return {@code true} if system is ready, {@code false} otherwise.
     */
+4 −2
Original line number Diff line number Diff line
@@ -607,6 +607,7 @@ public class Process {
     *                             started.
     * @param pkgDataInfoMap Map from related package names to private data directory
     *                       volume UUID and inode number.
     * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
     * @param zygoteArgs Additional arguments to supply to the zygote process.
     * @return An object that describes the result of the attempt to start the process.
     * @throws RuntimeException on fatal start failure
@@ -630,12 +631,13 @@ public class Process {
                                           @Nullable long[] disabledCompatChanges,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   pkgDataInfoMap,
                                           boolean bindMountAppStorageDirs,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, zygoteArgs);
                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
    }

    /** @hide */
@@ -659,7 +661,7 @@ public class Process {
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
                disabledCompatChanges, /* pkgDataInfoMap */ null, zygoteArgs);
                disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs);
    }

    /**
+12 −2
Original line number Diff line number Diff line
@@ -333,6 +333,7 @@ public class ZygoteProcess {
     *                             started.
     * @param pkgDataInfoMap Map from related package names to private data directory
     *                       volume UUID and inode number.
     * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
     *
     * @param zygoteArgs Additional arguments to supply to the Zygote process.
     * @return An object that describes the result of the attempt to start the process.
@@ -354,6 +355,7 @@ public class ZygoteProcess {
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  boolean bindMountAppStorageDirs,
                                                  @Nullable String[] zygoteArgs) {
        // TODO (chriswailes): Is there a better place to check this value?
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -365,7 +367,7 @@ public class ZygoteProcess {
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, zygoteArgs);
                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
@@ -606,6 +608,7 @@ public class ZygoteProcess {
     * @param disabledCompatChanges a list of disabled compat changes for the process being started.
     * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
     *                       and inode number.
     * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
     * @param extraArgs Additional arguments to supply to the zygote process.
     * @return An object that describes the result of the attempt to start the process.
     * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -628,6 +631,7 @@ public class ZygoteProcess {
                                                      @Nullable long[] disabledCompatChanges,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              pkgDataInfoMap,
                                                      boolean bindMountAppStorageDirs,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<>();
@@ -725,6 +729,10 @@ public class ZygoteProcess {
            argsForZygote.add(sb.toString());
        }

        if (bindMountAppStorageDirs) {
            argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
        }

        if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("--disabled-compat-changes=");
@@ -1282,7 +1290,9 @@ public class ZygoteProcess {
                    abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                    true /* startChildZygote */, null /* packageName */,
                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
                    null /* disabledCompatChanges */, null /* pkgDataInfoMap */, extraArgs);
                    null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
                    /* bindMountAppStorageDirs */ false, extraArgs);

        } catch (ZygoteStartFailedEx ex) {
            throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
        }
+4 −3
Original line number Diff line number Diff line
@@ -100,10 +100,11 @@ public abstract class StorageManagerInternal {
    }

    /**
     * Check if fuse is running in target user, if it's running then setup its obb directories.
     * TODO: System server should store a list of active pids that obb is not mounted and use it.
     * Create storage directories if it does not exist.
     * Return true if the directories were setup correctly, otherwise false.
     */
    public abstract void prepareObbDirs(int userId, Set<String> packageList, String processName);
    public abstract boolean prepareStorageDirs(int userId, Set<String> packageList,
            String processName);

    /**
     * Add a listener to listen to reset event in StorageManagerService.
+13 −7
Original line number Diff line number Diff line
@@ -178,6 +178,9 @@ public final class Zygote {
    /** List of packages with the same uid, and its app data info: volume uuid and inode. */
    public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";

    /** Bind mount app storage dirs to lower fs not via fuse */
    public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";

    /**
     * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
     * in the abstract socket namespace. This socket name is what the new child zygote
@@ -283,6 +286,7 @@ public final class Zygote {
     * @param isTopApp true if the process is for top (high priority) application.
     * @param pkgDataInfoList A list that stores related packages and its app data
     * info: volume uuid and inode.
     * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
@@ -290,13 +294,13 @@ public final class Zygote {
    static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            boolean isTopApp, String[] pkgDataInfoList) {
            boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
        ZygoteHooks.preFork();

        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList);
                pkgDataInfoList, bindMountAppStorageDirs);
        if (pid == 0) {
            // Note that this event ends at the end of handleChildProc,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -312,7 +316,8 @@ public final class Zygote {
    private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
            int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
            int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
            String appDataDir, boolean isTopApp, String[] pkgDataInfoList);
            String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
            boolean bindMountAppStorageDirs);

    /**
     * Specialize an unspecialized app process.  The current VM must have been started
@@ -339,14 +344,15 @@ public final class Zygote {
     * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
     * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
     * app_b_ce_inode, ...];
     * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
     */
    private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName,
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
            String[] pkgDataInfoList) {
            String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
        nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList);
                pkgDataInfoList, bindMountAppStorageDirs);

        // Note that this event ends at the end of handleChildProc.
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -366,7 +372,7 @@ public final class Zygote {
    private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
            int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
            String[] pkgDataInfoList);
            String[] pkgDataInfoList, boolean bindMountAppStorageDirs);

    /**
     * Called to do any initialization before starting an application.
@@ -691,7 +697,7 @@ public final class Zygote {
                                 args.mRuntimeFlags, rlimits, args.mMountExternal,
                                 args.mSeInfo, args.mNiceName, args.mStartChildZygote,
                                 args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
                                 args.mPkgDataInfoList);
                                 args.mPkgDataInfoList, args.mBindMountAppStorageDirs);

            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

Loading