Reconcile private volumes when mounted.

Many things can happen while a private volume is ejected, so we need
to reconcile newly mounted volumes against known state.

First, user IDs can be recycled, so we store the serial number in the
extended attributes of the /data/user/[id] directory inode.  Since a
serial number is always unique, we can quickly determine if a user
directory "10" really belongs to the current user "10".  When we
detect a mismatched serial number, we destroy all data belonging to
that user.  Gracefully handles upgrade case and assumes current serial
number is valid when none is defined.

Second, we destroy apps that we find no record of, either due to
uninstallation while the volume was unmounted, or reinstallation on
another volume.

When mounting a volume, ensure that data directories exist for all
current users.  Similarly, create data directories on all mounted
volumes when creating a user.  When forgetting a volume, gracefully
uninstall any apps that had been installed on that volume.

Bug: 20674082, 20275572
Change-Id: I4e3448837f7c03daf00d71681ebdc96e3d8b9cc9
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 8e0584a..2080856 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -244,14 +244,36 @@
     }
 
     /** {@hide} */
-    public static File getDataAppDirectory(String volumeUuid) {
+    public static File getDataDirectory(String volumeUuid) {
         if (TextUtils.isEmpty(volumeUuid)) {
-            return new File("/data/app");
+            return new File("/data");
         } else {
-            return new File("/mnt/expand/" + volumeUuid + "/app");
+            return new File("/mnt/expand/" + volumeUuid);
         }
     }
 
+    /** {@hide} */
+    public static File getDataAppDirectory(String volumeUuid) {
+        return new File(getDataDirectory(volumeUuid), "app");
+    }
+
+    /** {@hide} */
+    public static File getDataUserDirectory(String volumeUuid) {
+        return new File(getDataDirectory(volumeUuid), "user");
+    }
+
+    /** {@hide} */
+    public static File getDataUserDirectory(String volumeUuid, int userId) {
+        return new File(getDataUserDirectory(volumeUuid), String.valueOf(userId));
+    }
+
+    /** {@hide} */
+    public static File getDataUserPackageDirectory(String volumeUuid, int userId,
+            String packageName) {
+        // TODO: keep consistent with installd
+        return new File(getDataUserDirectory(volumeUuid, userId), packageName);
+    }
+
     /**
      * Return the primary external storage directory. This directory may not
      * currently be accessible if it has been mounted by the user on their