Plumbing in PackageManager and installd for multi-user support.

- Create /data/user directory and symlink /data/user/0 -> /data/data for
  backward compatibility
- Create data directories for all packages for new user

- Remove data directories when removing a user

- Create data directories for all users when a package is created

- Clear / Remove data for multiple users

- Fixed a bug in verifying the location of a system app

- pm commands for createUser and removeUser (will be disabled later)

- symlink duplicate lib directories to the original lib directory

Change-Id: Id9fdfcf0e62406a8896aa811314dfc08d5f6ed95
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index e0d0f97..c062d36 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -49,7 +49,7 @@
 
 static int do_remove(char **arg, char reply[REPLY_MAX])
 {
-    return uninstall(arg[0]); /* pkgname */
+    return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
 }
 
 static int do_rename(char **arg, char reply[REPLY_MAX])
@@ -92,7 +92,17 @@
 
 static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
 {
-    return delete_user_data(arg[0]); /* pkgname */
+    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
+}
+
+static int do_mk_user_data(char **arg, char reply[REPLY_MAX])
+{
+    return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
+}
+
+static int do_rm_user(char **arg, char reply[REPLY_MAX])
+{
+    return delete_persona(atoi(arg[0])); /* userid */
 }
 
 static int do_movefiles(char **arg, char reply[REPLY_MAX])
@@ -122,16 +132,18 @@
     { "dexopt",               3, do_dexopt },
     { "movedex",              2, do_move_dex },
     { "rmdex",                1, do_rm_dex },
-    { "remove",               1, do_remove },
+    { "remove",               2, do_remove },
     { "rename",               2, do_rename },
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
     { "protect",              2, do_protect },
     { "getsize",              3, do_get_size },
-    { "rmuserdata",           1, do_rm_user_data },
+    { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
     { "unlinklib",            1, do_unlinklib },
+    { "mkuserdata",           3, do_mk_user_data },
+    { "rmuser",               1, do_rm_user },
 };
 
 static int readx(int s, void *_buf, int count)
@@ -286,14 +298,50 @@
         return -1;
     }
 
+    // append "app/" to dirs[0]
+    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
+    android_system_dirs.dirs[0].path = system_app_path;
+    android_system_dirs.dirs[0].len = strlen(system_app_path);
+
     // vendor
     // TODO replace this with an environment variable (doesn't exist yet)
-    android_system_dirs.dirs[1].path = "/vendor/";
+    android_system_dirs.dirs[1].path = "/vendor/app/";
     android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
 
     return 0;
 }
 
+int initialize_directories() {
+    // /data/user
+    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
+    // /data/data
+    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
+    // /data/user/0
+    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX,
+            "0");
+    int ret = -1;
+    if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) {
+        ret = 0;
+        // Make the /data/user directory if necessary
+        if (access(user_data_dir, R_OK) < 0) {
+            if (mkdir(user_data_dir, 0755) < 0) {
+                return -1;
+            }
+            if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
+                return -1;
+            }
+        }
+        // Make the /data/user/0 symlink to /data/data if necessary
+        if (access(primary_data_dir, R_OK) < 0) {
+              ret = symlink(legacy_data_dir, primary_data_dir);
+        }
+        free(user_data_dir);
+        free(legacy_data_dir);
+        free(primary_data_dir);
+    }
+    return ret;
+}
+
 int main(const int argc, const char *argv[]) {
     char buf[BUFFER_MAX];
     struct sockaddr addr;
@@ -305,6 +353,11 @@
         exit(1);
     }
 
+    if (initialize_directories() < 0) {
+        LOGE("Could not create directories; exiting.\n");
+        exit(1);
+    }
+
     lsocket = android_get_control_socket(SOCKET_PATH);
     if (lsocket < 0) {
         LOGE("Failed to get socket from environment: %s\n", strerror(errno));