Loading cmds/installd/commands.c +38 −7 Original line number Diff line number Diff line Loading @@ -78,15 +78,15 @@ int install(const char *pkgname, uid_t uid, gid_t gid) return 0; } int uninstall(const char *pkgname) int uninstall(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, 0); return delete_dir_contents(pkgdir, 1, NULL); } int renamepkg(const char *oldpkgname, const char *newpkgname) Loading @@ -106,17 +106,48 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } int delete_user_data(const char *pkgname) int delete_user_data(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); } int make_user_data(const char *pkgname, uid_t uid, uid_t persona) { char pkgdir[PKG_PATH_MAX]; char real_libdir[PKG_PATH_MAX]; // Create the data dir for the package if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) { return -1; } if (mkdir(pkgdir, 0751) < 0) { LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); return -errno; } if (chown(pkgdir, uid, uid) < 0) { LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; } return 0; } int delete_persona(uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_persona_path(pkgdir, persona)) return -1; return delete_dir_contents(pkgdir, 1, NULL); } int delete_cache(const char *pkgname) { char cachedir[PKG_PATH_MAX]; Loading cmds/installd/installd.c +58 −5 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 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]) Loading Loading @@ -92,7 +92,17 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) 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]) Loading Loading @@ -122,16 +132,18 @@ struct cmdinfo cmds[] = { { "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) Loading Loading @@ -286,14 +298,50 @@ int initialize_globals() { 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; Loading @@ -305,6 +353,11 @@ int main(const int argc, const char *argv[]) { 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)); Loading cmds/installd/installd.h +10 −2 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *postfix, uid_t persona); int create_persona_path(char path[PKG_PATH_MAX], uid_t persona); int is_valid_package_name(const char* pkgname); int create_cache_path(char path[PKG_PATH_MAX], const char *src); Loading @@ -124,12 +127,17 @@ int validate_apk_path(const char *path); int append_and_increment(char** dst, const char* src, size_t* dst_size); char *build_string2(char *s1, char *s2); char *build_string3(char *s1, char *s2, char *s3); /* commands.c */ int install(const char *pkgname, uid_t uid, gid_t gid); int uninstall(const char *pkgname); int uninstall(const char *pkgname, uid_t persona); int renamepkg(const char *oldpkgname, const char *newpkgname); int delete_user_data(const char *pkgname); int delete_user_data(const char *pkgname, uid_t persona); int make_user_data(const char *pkgname, uid_t uid, uid_t persona); int delete_persona(uid_t persona); int delete_cache(const char *pkgname); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); Loading cmds/installd/utils.c +72 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,46 @@ int create_pkg_path(char path[PKG_PATH_MAX], return create_pkg_path_in_dir(path, &dir, pkgname, postfix); } /** * Create the path name for user data for a certain persona. * Returns 0 on success, and -1 on failure. */ int create_persona_path(char path[PKG_PATH_MAX], uid_t persona) { size_t uid_len; char* persona_prefix; if (persona == 0) { persona_prefix = PRIMARY_USER_PREFIX; uid_len = 0; } else { persona_prefix = SECONDARY_USER_PREFIX; uid_len = snprintf(NULL, 0, "%d", persona); } char *dst = path; size_t dst_size = PKG_PATH_MAX; if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { LOGE("Error building prefix for user path"); return -1; } if (persona != 0) { if (dst_size < uid_len + 1) { LOGE("Error building user path"); return -1; } int ret = snprintf(dst, dst_size, "%d", persona); if (ret < 0 || (size_t) ret != uid_len) { LOGE("Error appending persona id to path"); return -1; } } return 0; } /** * Checks whether the package name is valid. Returns -1 on error and * 0 on success. Loading Loading @@ -408,3 +448,35 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size) { *dst_size -= ret; return 0; } char *build_string2(char *s1, char *s2) { if (s1 == NULL || s2 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len = len_s1 + len_s2 + 1; char *result = malloc(len); if (result == NULL) return NULL; strcpy(result, s1); strcpy(result + len_s1, s2); return result; } char *build_string3(char *s1, char *s2, char *s3) { if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len_s3 = strlen(s3); int len = len_s1 + len_s2 + len_s3 + 1; char *result = malloc(len); if (result == NULL) return NULL; strcpy(result, s1); strcpy(result + len_s1, s2); strcpy(result + len_s1 + len_s2, s3); return result; } cmds/pm/src/com/android/commands/pm/Pm.java +71 −1 Original line number Diff line number Diff line Loading @@ -35,9 +35,9 @@ import android.content.pm.PermissionInfo; import android.content.res.AssetManager; import android.content.res.Resources; import android.net.Uri; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import java.io.File; import java.lang.reflect.Field; Loading @@ -60,6 +60,7 @@ public final class Pm { private static final String PM_NOT_RUNNING_ERR = "Error: Could not access the Package Manager. Is the system running?"; private static final int ROOT_UID = 0; public static void main(String[] args) { new Pm().run(args); Loading Loading @@ -127,6 +128,16 @@ public final class Pm { return; } if ("createUser".equals(op)) { runCreateUser(); return; } if ("removeUser".equals(op)) { runRemoveUser(); return; } try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { Loading Loading @@ -763,6 +774,63 @@ public final class Pm { } } public void runCreateUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { System.err.println("Error: createUser must be run as root"); return; } String name; String arg = nextArg(); if (arg == null) { System.err.println("Error: no user name specified."); showUsage(); return; } name = arg; try { if (mPm.createUser(name, 0) == null) { System.err.println("Error: couldn't create user."); showUsage(); } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } } public void runRemoveUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { System.err.println("Error: removeUser must be run as root"); return; } int userId; String arg = nextArg(); if (arg == null) { System.err.println("Error: no user id specified."); showUsage(); return; } try { userId = Integer.parseInt(arg); } catch (NumberFormatException e) { System.err.println("Error: user id has to be a number."); showUsage(); return; } try { if (!mPm.removeUser(userId)) { System.err.println("Error: couldn't remove user."); showUsage(); } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } } class PackageDeleteObserver extends IPackageDeleteObserver.Stub { boolean finished; boolean result; Loading Loading @@ -1006,6 +1074,8 @@ public final class Pm { System.err.println(" pm enable PACKAGE_OR_COMPONENT"); System.err.println(" pm disable PACKAGE_OR_COMPONENT"); System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]"); System.err.println(" pm createUser USER_NAME"); System.err.println(" pm removeUser USER_ID"); System.err.println(""); System.err.println("The list packages command prints all packages, optionally only"); System.err.println("those whose package name contains the text in FILTER. Options:"); Loading Loading
cmds/installd/commands.c +38 −7 Original line number Diff line number Diff line Loading @@ -78,15 +78,15 @@ int install(const char *pkgname, uid_t uid, gid_t gid) return 0; } int uninstall(const char *pkgname) int uninstall(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, 0); return delete_dir_contents(pkgdir, 1, NULL); } int renamepkg(const char *oldpkgname, const char *newpkgname) Loading @@ -106,17 +106,48 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } int delete_user_data(const char *pkgname) int delete_user_data(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); } int make_user_data(const char *pkgname, uid_t uid, uid_t persona) { char pkgdir[PKG_PATH_MAX]; char real_libdir[PKG_PATH_MAX]; // Create the data dir for the package if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) { return -1; } if (mkdir(pkgdir, 0751) < 0) { LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); return -errno; } if (chown(pkgdir, uid, uid) < 0) { LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; } return 0; } int delete_persona(uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_persona_path(pkgdir, persona)) return -1; return delete_dir_contents(pkgdir, 1, NULL); } int delete_cache(const char *pkgname) { char cachedir[PKG_PATH_MAX]; Loading
cmds/installd/installd.c +58 −5 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 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]) Loading Loading @@ -92,7 +92,17 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) 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]) Loading Loading @@ -122,16 +132,18 @@ struct cmdinfo cmds[] = { { "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) Loading Loading @@ -286,14 +298,50 @@ int initialize_globals() { 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; Loading @@ -305,6 +353,11 @@ int main(const int argc, const char *argv[]) { 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)); Loading
cmds/installd/installd.h +10 −2 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *postfix, uid_t persona); int create_persona_path(char path[PKG_PATH_MAX], uid_t persona); int is_valid_package_name(const char* pkgname); int create_cache_path(char path[PKG_PATH_MAX], const char *src); Loading @@ -124,12 +127,17 @@ int validate_apk_path(const char *path); int append_and_increment(char** dst, const char* src, size_t* dst_size); char *build_string2(char *s1, char *s2); char *build_string3(char *s1, char *s2, char *s3); /* commands.c */ int install(const char *pkgname, uid_t uid, gid_t gid); int uninstall(const char *pkgname); int uninstall(const char *pkgname, uid_t persona); int renamepkg(const char *oldpkgname, const char *newpkgname); int delete_user_data(const char *pkgname); int delete_user_data(const char *pkgname, uid_t persona); int make_user_data(const char *pkgname, uid_t uid, uid_t persona); int delete_persona(uid_t persona); int delete_cache(const char *pkgname); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); Loading
cmds/installd/utils.c +72 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,46 @@ int create_pkg_path(char path[PKG_PATH_MAX], return create_pkg_path_in_dir(path, &dir, pkgname, postfix); } /** * Create the path name for user data for a certain persona. * Returns 0 on success, and -1 on failure. */ int create_persona_path(char path[PKG_PATH_MAX], uid_t persona) { size_t uid_len; char* persona_prefix; if (persona == 0) { persona_prefix = PRIMARY_USER_PREFIX; uid_len = 0; } else { persona_prefix = SECONDARY_USER_PREFIX; uid_len = snprintf(NULL, 0, "%d", persona); } char *dst = path; size_t dst_size = PKG_PATH_MAX; if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { LOGE("Error building prefix for user path"); return -1; } if (persona != 0) { if (dst_size < uid_len + 1) { LOGE("Error building user path"); return -1; } int ret = snprintf(dst, dst_size, "%d", persona); if (ret < 0 || (size_t) ret != uid_len) { LOGE("Error appending persona id to path"); return -1; } } return 0; } /** * Checks whether the package name is valid. Returns -1 on error and * 0 on success. Loading Loading @@ -408,3 +448,35 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size) { *dst_size -= ret; return 0; } char *build_string2(char *s1, char *s2) { if (s1 == NULL || s2 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len = len_s1 + len_s2 + 1; char *result = malloc(len); if (result == NULL) return NULL; strcpy(result, s1); strcpy(result + len_s1, s2); return result; } char *build_string3(char *s1, char *s2, char *s3) { if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len_s3 = strlen(s3); int len = len_s1 + len_s2 + len_s3 + 1; char *result = malloc(len); if (result == NULL) return NULL; strcpy(result, s1); strcpy(result + len_s1, s2); strcpy(result + len_s1 + len_s2, s3); return result; }
cmds/pm/src/com/android/commands/pm/Pm.java +71 −1 Original line number Diff line number Diff line Loading @@ -35,9 +35,9 @@ import android.content.pm.PermissionInfo; import android.content.res.AssetManager; import android.content.res.Resources; import android.net.Uri; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import java.io.File; import java.lang.reflect.Field; Loading @@ -60,6 +60,7 @@ public final class Pm { private static final String PM_NOT_RUNNING_ERR = "Error: Could not access the Package Manager. Is the system running?"; private static final int ROOT_UID = 0; public static void main(String[] args) { new Pm().run(args); Loading Loading @@ -127,6 +128,16 @@ public final class Pm { return; } if ("createUser".equals(op)) { runCreateUser(); return; } if ("removeUser".equals(op)) { runRemoveUser(); return; } try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { Loading Loading @@ -763,6 +774,63 @@ public final class Pm { } } public void runCreateUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { System.err.println("Error: createUser must be run as root"); return; } String name; String arg = nextArg(); if (arg == null) { System.err.println("Error: no user name specified."); showUsage(); return; } name = arg; try { if (mPm.createUser(name, 0) == null) { System.err.println("Error: couldn't create user."); showUsage(); } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } } public void runRemoveUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { System.err.println("Error: removeUser must be run as root"); return; } int userId; String arg = nextArg(); if (arg == null) { System.err.println("Error: no user id specified."); showUsage(); return; } try { userId = Integer.parseInt(arg); } catch (NumberFormatException e) { System.err.println("Error: user id has to be a number."); showUsage(); return; } try { if (!mPm.removeUser(userId)) { System.err.println("Error: couldn't remove user."); showUsage(); } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } } class PackageDeleteObserver extends IPackageDeleteObserver.Stub { boolean finished; boolean result; Loading Loading @@ -1006,6 +1074,8 @@ public final class Pm { System.err.println(" pm enable PACKAGE_OR_COMPONENT"); System.err.println(" pm disable PACKAGE_OR_COMPONENT"); System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]"); System.err.println(" pm createUser USER_NAME"); System.err.println(" pm removeUser USER_ID"); System.err.println(""); System.err.println("The list packages command prints all packages, optionally only"); System.err.println("those whose package name contains the text in FILTER. Options:"); Loading