Multi-user external storage support.
Emulated external storage always has multi-user support using paths
like "/data/media/<user_id>". Creates and destroys these paths along
with user data. Uses new ensure_dir() to create directories while
always ensuring permissions.
Add external storage mount mode to zygote, supporting both single-
and multi-user devices. For example, devices with physical SD cards
are treated as single-user. Begin migrating to mount mode instead
of relying on sdcard_r GID to enforce READ_EXTERNAL_STORAGE.
Bug: 6925012
Change-Id: I9b872ded992cd078e2c013567d59f9f0032ec02b
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 93860aa..a3b665a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -376,12 +376,13 @@
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
- int debugFlags, int targetSdkVersion,
+ int debugFlags, int mountExternal,
+ int targetSdkVersion,
String seInfo,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, targetSdkVersion, seInfo, zygoteArgs);
+ debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -553,7 +554,8 @@
final String niceName,
final int uid, final int gid,
final int[] gids,
- int debugFlags, int targetSdkVersion,
+ int debugFlags, int mountExternal,
+ int targetSdkVersion,
String seInfo,
String[] extraArgs)
throws ZygoteStartFailedEx {
@@ -580,6 +582,11 @@
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
+ if (mountExternal == Zygote.MOUNT_EXTERNAL_SINGLEUSER) {
+ argsForZygote.add("--mount-external-singleuser");
+ } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
+ argsForZygote.add("--mount-external-multiuser");
+ }
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b016e99..1e268c4 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,16 +18,14 @@
import android.net.Credentials;
import android.net.LocalSocket;
-import android.os.Build;
import android.os.Process;
+import android.os.SELinux;
import android.os.SystemProperties;
import android.util.Log;
import dalvik.system.PathClassLoader;
import dalvik.system.Zygote;
-import android.os.SELinux;
-
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -234,9 +232,9 @@
ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, parsedArgs.debugFlags, rlimits,
- parsedArgs.seInfo, parsedArgs.niceName);
+ pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
+ parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
+ parsedArgs.niceName);
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
@@ -341,6 +339,9 @@
*/
int debugFlags;
+ /** From --mount-external */
+ int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
+
/** from --target-sdk-version. */
int targetSdkVersion;
boolean targetSdkVersionSpecified;
@@ -526,6 +527,10 @@
"Duplicate arg specified");
}
niceName = arg.substring(arg.indexOf('=') + 1);
+ } else if (arg.equals("--mount-external-singleuser")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_SINGLEUSER;
+ } else if (arg.equals("--mount-external-multiuser")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
} else {
break;
}