Introduce ephemeral users.

BUG: 24883058

Change-Id: I2e1d6aa184142c2a3dc0415c0cd407573453cf41
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 473eff6..184f890 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2716,12 +2716,13 @@
     }
 
     @Override
-    public void createUserKey(int userId, int serialNumber) {
+    public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
         waitForReady();
 
         try {
-            mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber);
+            mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber,
+                ephemeral ? 1 : 0);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
@@ -2797,13 +2798,14 @@
     }
 
     @Override
-    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber) {
+    public void prepareUserStorage(
+            String volumeUuid, int userId, int serialNumber, boolean ephemeral) {
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
         waitForReady();
 
         try {
             mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid),
-                    userId, serialNumber);
+                    userId, serialNumber, ephemeral ? 1 : 0);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d94e5f4..ab8e5a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16450,7 +16450,7 @@
             if (userDir.exists()) continue;
 
             try {
-                sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber);
+                sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, user.isEphemeral());
                 UserManagerService.enforceSerialNumber(userDir, user.serialNumber);
             } catch (IOException e) {
                 Log.wtf(TAG, "Failed to create user directory on " + volumeUuid, e);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e045758..4497e4d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -306,13 +306,13 @@
     }
 
     void systemReady() {
-        // Prune out any partially created/partially removed users.
+        // Prune out any partially created, partially removed and ephemeral users.
         ArrayList<UserInfo> partials = new ArrayList<>();
         synchronized (mUsersLock) {
             final int userSize = mUsers.size();
             for (int i = 0; i < userSize; i++) {
                 UserInfo ui = mUsers.valueAt(i);
-                if ((ui.partial || ui.guestToRemove) && i != 0) {
+                if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
                     partials.add(ui);
                 }
             }
@@ -1675,6 +1675,10 @@
                         }
                     }
                 }
+
+                if (parent != null && parent.isEphemeral()) {
+                    flags |= UserInfo.FLAG_EPHEMERAL;
+                }
                 userId = getNextAvailableId();
                 userInfo = new UserInfo(userId, name, null, flags);
                 userInfo.serialNumber = mNextSerialNumber++;
@@ -1703,12 +1707,13 @@
                 }
             }
             final StorageManager storage = mContext.getSystemService(StorageManager.class);
-            storage.createUserKey(userId, userInfo.serialNumber);
+            storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
             for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
                 final String volumeUuid = vol.getFsUuid();
                 try {
                     final File userDir = Environment.getDataUserDirectory(volumeUuid, userId);
-                    storage.prepareUserStorage(volumeUuid, userId, userInfo.serialNumber);
+                    storage.prepareUserStorage(
+                            volumeUuid, userId, userInfo.serialNumber, userInfo.isEphemeral());
                     enforceSerialNumber(userDir, userInfo.serialNumber);
                 } catch (IOException e) {
                     Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e);