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);
             }
         }