Move "volume" commands over to Binder.
Keep the old socket-based commands intact for awhile so we can
rapidly disable this change using the ENABLE_BINDER feature flag.
Define constants in AIDL to keep Java and C++ in sync.
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.ExternalStorageHostTest
Test: cts-tradefed run commandAndExit cts-dev --abi armeabi-v7a -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Bug: 13758960
Change-Id: Ie0d917c921b0b826e6bdf55a5d678b247ef352a6
diff --git a/Android.mk b/Android.mk
index 46fa0d6..a3a147b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -566,6 +566,7 @@
LOCAL_SRC_FILES += \
../../system/netd/server/binder/android/net/INetd.aidl \
+ ../../system/vold/binder/android/os/IVold.aidl \
../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index a21e05e..b8353d7 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -23,6 +23,7 @@
import android.content.res.Resources;
import android.net.Uri;
import android.os.Environment;
+import android.os.IVold;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
@@ -75,24 +76,24 @@
/** Real volume representing internal emulated storage */
public static final String ID_EMULATED_INTERNAL = "emulated";
- public static final int TYPE_PUBLIC = 0;
- public static final int TYPE_PRIVATE = 1;
- public static final int TYPE_EMULATED = 2;
- public static final int TYPE_ASEC = 3;
- public static final int TYPE_OBB = 4;
+ public static final int TYPE_PUBLIC = IVold.TYPE_PUBLIC;
+ public static final int TYPE_PRIVATE = IVold.TYPE_PRIVATE;
+ public static final int TYPE_EMULATED = IVold.TYPE_EMULATED;
+ public static final int TYPE_ASEC = IVold.TYPE_ASEC;
+ public static final int TYPE_OBB = IVold.TYPE_OBB;
- public static final int STATE_UNMOUNTED = 0;
- public static final int STATE_CHECKING = 1;
- public static final int STATE_MOUNTED = 2;
- public static final int STATE_MOUNTED_READ_ONLY = 3;
- public static final int STATE_FORMATTING = 4;
- public static final int STATE_EJECTING = 5;
- public static final int STATE_UNMOUNTABLE = 6;
- public static final int STATE_REMOVED = 7;
- public static final int STATE_BAD_REMOVAL = 8;
+ public static final int STATE_UNMOUNTED = IVold.STATE_UNMOUNTED;
+ public static final int STATE_CHECKING = IVold.STATE_CHECKING;
+ public static final int STATE_MOUNTED = IVold.STATE_MOUNTED;
+ public static final int STATE_MOUNTED_READ_ONLY = IVold.STATE_MOUNTED_READ_ONLY;
+ public static final int STATE_FORMATTING = IVold.STATE_FORMATTING;
+ public static final int STATE_EJECTING = IVold.STATE_EJECTING;
+ public static final int STATE_UNMOUNTABLE = IVold.STATE_UNMOUNTABLE;
+ public static final int STATE_REMOVED = IVold.STATE_REMOVED;
+ public static final int STATE_BAD_REMOVAL = IVold.STATE_BAD_REMOVAL;
- public static final int MOUNT_FLAG_PRIMARY = 1 << 0;
- public static final int MOUNT_FLAG_VISIBLE = 1 << 1;
+ public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY;
+ public static final int MOUNT_FLAG_VISIBLE = IVold.MOUNT_FLAG_VISIBLE;
private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index a9350db..4e4b5b8 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -16,14 +16,12 @@
package com.android.internal.os;
-
+import android.os.IVold;
import android.os.Trace;
-import dalvik.system.ZygoteHooks;
import android.system.ErrnoException;
import android.system.Os;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import dalvik.system.ZygoteHooks;
/** @hide */
public final class Zygote {
@@ -52,13 +50,13 @@
public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8;
/** No external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_NONE = 0;
+ public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_DEFAULT = 1;
+ public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT;
/** Read-only external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_READ = 2;
+ public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
/** Read-write external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_WRITE = 3;
+ public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b0528dc..02e8243 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -681,13 +681,18 @@
final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
boolean success = false;
try {
- success = mConnector.execute("volume", "shutdown").isClassOk();
- } catch (NativeDaemonConnectorException ignored) {
+ if (ENABLE_BINDER) {
+ mVold.shutdown();
+ } else {
+ success = mConnector.execute("volume", "shutdown").isClassOk();
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
if (obs != null) {
try {
obs.onShutDownComplete(success ? 0 : -1);
- } catch (RemoteException ignored) {
+ } catch (Exception ignored) {
}
}
break;
@@ -699,9 +704,14 @@
break;
}
try {
- mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
- vol.mountUserId);
- } catch (NativeDaemonConnectorException ignored) {
+ if (ENABLE_BINDER) {
+ mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+ } else {
+ mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
+ vol.mountUserId);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
break;
}
@@ -761,7 +771,11 @@
if (Intent.ACTION_USER_ADDED.equals(action)) {
final UserManager um = mContext.getSystemService(UserManager.class);
final int userSerialNumber = um.getUserSerialNumber(userId);
- mConnector.execute("volume", "user_added", userId, userSerialNumber);
+ if (ENABLE_BINDER) {
+ mVold.onUserAdded(userId, userSerialNumber);
+ } else {
+ mConnector.execute("volume", "user_added", userId, userSerialNumber);
+ }
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
synchronized (mVolumes) {
final int size = mVolumes.size();
@@ -773,10 +787,14 @@
}
}
}
- mConnector.execute("volume", "user_removed", userId);
+ if (ENABLE_BINDER) {
+ mVold.onUserRemoved(userId);
+ } else {
+ mConnector.execute("volume", "user_removed", userId);
+ }
}
- } catch (NativeDaemonConnectorException e) {
- Slog.w(TAG, "Failed to send user details to vold", e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
};
@@ -930,13 +948,21 @@
// Tell vold about all existing and started users
for (UserInfo user : users) {
- mConnector.execute("volume", "user_added", user.id, user.serialNumber);
+ if (ENABLE_BINDER) {
+ mVold.onUserAdded(user.id, user.serialNumber);
+ } else {
+ mConnector.execute("volume", "user_added", user.id, user.serialNumber);
+ }
}
for (int userId : systemUnlockedUsers) {
- mConnector.execute("volume", "user_started", userId);
+ if (ENABLE_BINDER) {
+ mVold.onUserStarted(userId);
+ } else {
+ mConnector.execute("volume", "user_started", userId);
+ }
}
- } catch (RemoteException | NativeDaemonConnectorException e) {
- Slog.w(TAG, "Failed to reset vold", e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
}
@@ -948,8 +974,13 @@
// staging area is ready so it's ready for zygote-forked apps to
// bind mount against.
try {
- mConnector.execute("volume", "user_started", userId);
- } catch (NativeDaemonConnectorException ignored) {
+ if (ENABLE_BINDER) {
+ mVold.onUserStarted(userId);
+ } else {
+ mConnector.execute("volume", "user_started", userId);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
// Record user as started so newly mounted volumes kick off events
@@ -973,8 +1004,13 @@
Slog.d(TAG, "onCleanupUser " + userId);
try {
- mConnector.execute("volume", "user_stopped", userId);
- } catch (NativeDaemonConnectorException ignored) {
+ if (ENABLE_BINDER) {
+ mVold.onUserStopped(userId);
+ } else {
+ mConnector.execute("volume", "user_stopped", userId);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
synchronized (mLock) {
@@ -1804,9 +1840,13 @@
throw new SecurityException("Mounting " + volId + " restricted by policy");
}
try {
- mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ if (ENABLE_BINDER) {
+ mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+ } else {
+ mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1833,9 +1873,13 @@
}
try {
- mConnector.execute("volume", "unmount", vol.id);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ if (ENABLE_BINDER) {
+ mVold.unmount(vol.id);
+ } else {
+ mConnector.execute("volume", "unmount", vol.id);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1846,9 +1890,13 @@
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
try {
- mConnector.execute("volume", "format", vol.id, "auto");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ if (ENABLE_BINDER) {
+ mVold.format(vol.id, "auto");
+ } else {
+ mConnector.execute("volume", "format", vol.id, "auto");
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1859,13 +1907,16 @@
try {
// TODO: make benchmark async so we don't block other commands
- final NativeDaemonEvent res = mConnector.execute(3 * DateUtils.MINUTE_IN_MILLIS,
- "volume", "benchmark", volId);
- return Long.parseLong(res.getMessage());
- } catch (NativeDaemonTimeoutException e) {
+ if (ENABLE_BINDER) {
+ return mVold.benchmark(volId);
+ } else {
+ final NativeDaemonEvent res = mConnector.execute(3 * DateUtils.MINUTE_IN_MILLIS,
+ "volume", "benchmark", volId);
+ return Long.parseLong(res.getMessage());
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
return Long.MAX_VALUE;
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
}
}
@@ -1876,12 +1927,14 @@
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- mConnector.execute("volume", "partition", diskId, "public");
+ if (ENABLE_BINDER) {
+ mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
+ } else {
+ mConnector.execute("volume", "partition", diskId, "public");
+ }
waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- } catch (TimeoutException e) {
- throw new IllegalStateException(e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1893,12 +1946,14 @@
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- mConnector.execute("volume", "partition", diskId, "private");
+ if (ENABLE_BINDER) {
+ mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
+ } else {
+ mConnector.execute("volume", "partition", diskId, "private");
+ }
waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- } catch (TimeoutException e) {
- throw new IllegalStateException(e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1910,12 +1965,14 @@
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- mConnector.execute("volume", "partition", diskId, "mixed", ratio);
+ if (ENABLE_BINDER) {
+ mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
+ } else {
+ mConnector.execute("volume", "partition", diskId, "mixed", ratio);
+ }
waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- } catch (TimeoutException e) {
- throw new IllegalStateException(e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -1999,9 +2056,13 @@
private void forgetPartition(String partGuid) {
try {
- mConnector.execute("volume", "forget_partition", partGuid);
- } catch (NativeDaemonConnectorException e) {
- Slog.w(TAG, "Failed to forget key for " + partGuid + ": " + e);
+ if (ENABLE_BINDER) {
+ mVold.forgetPartition(partGuid);
+ } else {
+ mConnector.execute("volume", "forget_partition", partGuid);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -2035,20 +2096,22 @@
case Zygote.MOUNT_EXTERNAL_DEFAULT: {
modeName = "default";
} break;
-
case Zygote.MOUNT_EXTERNAL_READ: {
modeName = "read";
} break;
-
case Zygote.MOUNT_EXTERNAL_WRITE: {
modeName = "write";
} break;
}
try {
- mConnector.execute("volume", "remount_uid", uid, modeName);
- } catch (NativeDaemonConnectorException e) {
- Slog.w(TAG, "Failed to remount UID " + uid + " as " + modeName + ": " + e);
+ if (ENABLE_BINDER) {
+ mVold.remountUid(uid, mode);
+ } else {
+ mConnector.execute("volume", "remount_uid", uid, modeName);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -2199,9 +2262,13 @@
}
try {
- mConnector.execute("volume", "move_storage", from.id, to.id);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ if (ENABLE_BINDER) {
+ mVold.moveStorage(from.id, to.id);
+ } else {
+ mConnector.execute("volume", "move_storage", from.id, to.id);
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
@@ -3185,10 +3252,14 @@
}
try {
- mConnector.execute("volume", "mkdirs", appPath);
+ if (ENABLE_BINDER) {
+ mVold.mkdirs(appPath);
+ } else {
+ mConnector.execute("volume", "mkdirs", appPath);
+ }
return 0;
- } catch (NativeDaemonConnectorException e) {
- return e.getCode();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}