summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorRicky Wai <rickywai@google.com>2020-02-28 16:37:07 +0000
committerRicky Wai <rickywai@google.com>2020-03-12 19:36:26 +0000
commit486d760e6bc791db3f449c6fc4c205e86cd4f2d5 (patch)
tree341ba0baf9e69e313bde481cd9cd0ae6beb32d0b /core/java/android
parenta8375cc9f85380254d18ae48b59e8954c0b7886e (diff)
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
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerInternal.java7
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/ZygoteProcess.java14
-rw-r--r--core/java/android/os/storage/StorageManagerInternal.java7
4 files changed, 27 insertions, 7 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index ec110435d95c..489a0de0518e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -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.
@@ -124,6 +125,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.
*/
public abstract boolean isSystemReady();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d7af1b9faa97..a557bd994c13 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -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);
}
/**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 34cec061edcd..5f3f14facd75 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -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);
}
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index a2def7fff2d2..f43a2523b5b3 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -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.