summaryrefslogtreecommitdiffstats
path: root/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'cmds')
-rw-r--r--cmds/installd/commands.c30
-rw-r--r--cmds/installd/installd.c150
-rw-r--r--cmds/installd/installd.h7
-rw-r--r--cmds/installd/utils.c50
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java41
-rw-r--r--cmds/svc/src/com/android/commands/svc/PowerCommand.java10
6 files changed, 251 insertions, 37 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d94daf7..c16e6fb 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -213,18 +213,30 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
int delete_persona(uid_t persona)
{
- char pkgdir[PKG_PATH_MAX];
+ char data_path[PKG_PATH_MAX];
+ if (create_persona_path(data_path, persona)) {
+ return -1;
+ }
+ if (delete_dir_contents(data_path, 1, NULL)) {
+ return -1;
+ }
- if (create_persona_path(pkgdir, persona))
+ char media_path[PATH_MAX];
+ if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
+ return -1;
+ }
+ if (delete_dir_contents(media_path, 1, NULL) == -1) {
return -1;
+ }
- return delete_dir_contents(pkgdir, 1, NULL);
+ return 0;
}
int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
{
char src_data_dir[PKG_PATH_MAX];
char pkg_path[PKG_PATH_MAX];
+ char media_path[PATH_MAX];
DIR *d;
struct dirent *de;
struct stat s;
@@ -233,6 +245,9 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
if (create_persona_path(src_data_dir, src_persona)) {
return -1;
}
+ if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) {
+ return -1;
+ }
d = opendir(src_data_dir);
if (d != NULL) {
@@ -260,6 +275,11 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
}
closedir(d);
}
+
+ // ensure /data/media/<user_id> exists
+ if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ return -1;
+ }
return 0;
}
@@ -412,7 +432,7 @@ int protect(char *pkgname, gid_t gid)
return 0;
}
-int get_size(const char *pkgname, const char *apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath,
const char *fwdlock_apkpath, const char *asecpath,
int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
int64_t* _asecsize)
@@ -459,7 +479,7 @@ int get_size(const char *pkgname, const char *apkpath,
}
}
- if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+ if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
goto done;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 89c059e..7108d68 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -85,8 +85,9 @@ static int do_get_size(char **arg, char reply[REPLY_MAX])
int64_t asecsize = 0;
int res = 0;
- /* pkgdir, apkpath */
- res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
+ /* pkgdir, persona, apkpath */
+ res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
+ &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -150,7 +151,7 @@ struct cmdinfo cmds[] = {
{ "freecache", 1, do_free_cache },
{ "rmcache", 1, do_rm_cache },
{ "protect", 2, do_protect },
- { "getsize", 4, do_get_size },
+ { "getsize", 5, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 2, do_linklib },
@@ -331,37 +332,138 @@ int initialize_globals() {
}
int initialize_directories() {
+ int res = -1;
+ int version = 0;
+ FILE* file;
+
+ // Read current filesystem layout version to handle upgrade paths
+ char version_path[PATH_MAX];
+ if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) {
+ return -1;
+ }
+ file = fopen(version_path, "r");
+ if (file != NULL) {
+ fscanf(file, "%d", &version);
+ fclose(file);
+ }
+
// /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, 0711) < 0) {
- return -1;
- }
- if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
- return -1;
+ char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
+ if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
+ goto fail;
+ }
+
+ // Make the /data/user directory if necessary
+ if (access(user_data_dir, R_OK) < 0) {
+ if (mkdir(user_data_dir, 0711) < 0) {
+ goto fail;
+ }
+ if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
+ goto fail;
+ }
+ if (chmod(user_data_dir, 0711) < 0) {
+ goto fail;
+ }
+ }
+ // Make the /data/user/0 symlink to /data/data if necessary
+ if (access(primary_data_dir, R_OK) < 0) {
+ if (symlink(legacy_data_dir, primary_data_dir)) {
+ goto fail;
+ }
+ }
+
+ // /data/media/0
+ char owner_media_dir[PATH_MAX];
+ create_persona_media_path(owner_media_dir, 0);
+
+ if (version == 0) {
+ // Introducing multi-user, so migrate /data/media contents into /data/media/0
+ ALOGD("Migrating /data/media for multi-user");
+
+ // /data/media.tmp
+ char media_tmp_dir[PATH_MAX];
+ snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
+
+ // Only copy when upgrade not already in progress
+ if (access(media_tmp_dir, F_OK) == -1) {
+ if (rename(android_media_dir.path, media_tmp_dir) == -1) {
+ ALOGE("Failed to move legacy media path: %s", strerror(errno));
+ goto fail;
}
- if (chmod(user_data_dir, 0711) < 0) {
- return -1;
+ }
+
+ // Create /data/media again
+ if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ goto fail;
+ }
+
+ // Move any owner data into place
+ if (access(media_tmp_dir, F_OK) == 0) {
+ if (rename(media_tmp_dir, owner_media_dir) == -1) {
+ ALOGE("Failed to move owner media path: %s", strerror(errno));
+ goto fail;
}
}
- // 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);
+
+ // Ensure media directories for any existing users
+ DIR *dir;
+ struct dirent *dirent;
+ char user_media_dir[PATH_MAX];
+
+ dir = opendir(user_data_dir);
+ if (dir != NULL) {
+ while ((dirent = readdir(dir))) {
+ if (dirent->d_type == DT_DIR) {
+ const char *name = dirent->d_name;
+
+ // skip "." and ".."
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ // /data/media/<user_id>
+ snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
+ if (ensure_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ ALOGE("Failed to ensure %s: %s", user_media_dir, strerror(errno));
+ goto fail;
+ }
+ }
+ }
+ closedir(dir);
}
- free(user_data_dir);
- free(legacy_data_dir);
- free(primary_data_dir);
+
+ version = 1;
}
- return ret;
+
+ // Ensure /data/media/0 is always ready
+ if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ goto fail;
+ }
+
+ // Persist our current version
+ file = fopen(version_path, "w");
+ if (file != NULL) {
+ fprintf(file, "%d", version);
+ fsync(fileno(file));
+ fclose(file);
+ } else {
+ ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+ goto fail;
+ }
+
+ // Success!
+ res = 0;
+
+fail:
+ free(user_data_dir);
+ free(legacy_data_dir);
+ free(primary_data_dir);
+ return res;
}
int main(const int argc, const char *argv[]) {
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index f5853ff..3201427 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -35,6 +35,7 @@
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
+#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
@@ -138,6 +139,8 @@ int create_pkg_path(char path[PKG_PATH_MAX],
int create_persona_path(char path[PKG_PATH_MAX],
uid_t persona);
+int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
+
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
@@ -180,6 +183,8 @@ 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);
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+
/* commands.c */
int install(const char *pkgname, uid_t uid, gid_t gid);
@@ -194,7 +199,7 @@ int delete_cache(const char *pkgname);
int move_dex(const char *src, const char *dst);
int rm_dex(const char *path);
int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
int64_t *asecsize);
int free_cache(int64_t free_size);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 79db972..80247f1 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -137,6 +137,17 @@ int create_persona_path(char path[PKG_PATH_MAX],
return 0;
}
+/**
+ * Create the path name for media for a certain persona.
+ * Returns 0 on success, and -1 on failure.
+ */
+int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
+ if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
+ return -1;
+ }
+ return 0;
+}
+
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
@@ -979,3 +990,42 @@ char *build_string3(char *s1, char *s2, char *s3) {
return result;
}
+
+/* Ensure that directory exists with given mode and owners. */
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
+ // Check if path needs to be created
+ struct stat sb;
+ if (stat(path, &sb) == -1) {
+ if (errno == ENOENT) {
+ goto create;
+ } else {
+ ALOGE("Failed to stat(%s): %s", path, strerror(errno));
+ return -1;
+ }
+ }
+
+ // Exists, verify status
+ if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) {
+ return 0;
+ } else {
+ goto fixup;
+ }
+
+create:
+ if (mkdir(path, mode) == -1) {
+ ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
+ return -1;
+ }
+
+fixup:
+ if (chown(path, uid, gid) == -1) {
+ ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
+ return -1;
+ }
+ if (chmod(path, mode) == -1) {
+ ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index eb1f9a2..b34fd05 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -36,6 +36,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
@@ -787,6 +788,8 @@ public final class Pm {
String macAlgo = null;
byte[] macKey = null;
byte[] tag = null;
+ String originatingUriString = null;
+ String referrer = null;
while ((opt=nextOption()) != null) {
if (opt.equals("-l")) {
@@ -850,6 +853,20 @@ public final class Pm {
showUsage();
return;
}
+ } else if (opt.equals("--originating-uri")) {
+ originatingUriString = nextOptionData();
+ if (originatingUriString == null) {
+ System.err.println("Error: must supply argument for --originating-uri");
+ showUsage();
+ return;
+ }
+ } else if (opt.equals("--referrer")) {
+ referrer = nextOptionData();
+ if (referrer == null) {
+ System.err.println("Error: must supply argument for --referrer");
+ showUsage();
+ return;
+ }
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
@@ -897,6 +914,20 @@ public final class Pm {
final Uri apkURI;
final Uri verificationURI;
+ final Uri originatingURI;
+ final Uri referrerURI;
+
+ if (originatingUriString != null) {
+ originatingURI = Uri.parse(originatingUriString);
+ } else {
+ originatingURI = null;
+ }
+
+ if (referrer != null) {
+ referrerURI = Uri.parse(referrer);
+ } else {
+ referrerURI = null;
+ }
// Populate apkURI, must be present
final String apkFilePath = nextArg();
@@ -920,8 +951,11 @@ public final class Pm {
PackageInstallObserver obs = new PackageInstallObserver();
try {
- mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
- verificationURI, null, encryptionParams);
+ VerificationParams verificationParams = new VerificationParams(verificationURI,
+ originatingURI, referrerURI, null);
+
+ mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+ installerPackageName, verificationParams, encryptionParams);
synchronized (obs) {
while (!obs.finished) {
@@ -1441,7 +1475,8 @@ public final class Pm {
System.err.println(" pm list libraries");
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
- System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
+ System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
+ System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
System.err.println(" pm clear PACKAGE");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index deef2a3..ec3ec3e 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -37,7 +37,7 @@ public class PowerCommand extends Svc.Command {
public String longHelp() {
return shortHelp() + "\n"
+ "\n"
- + "usage: svc power stayon [true|false|usb|ac]\n"
+ + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
+ " Set the 'keep awake while plugged in' setting.\n";
}
@@ -48,7 +48,8 @@ public class PowerCommand extends Svc.Command {
int val;
if ("true".equals(args[2])) {
val = BatteryManager.BATTERY_PLUGGED_AC |
- BatteryManager.BATTERY_PLUGGED_USB;
+ BatteryManager.BATTERY_PLUGGED_USB |
+ BatteryManager.BATTERY_PLUGGED_WIRELESS;
}
else if ("false".equals(args[2])) {
val = 0;
@@ -56,8 +57,9 @@ public class PowerCommand extends Svc.Command {
val = BatteryManager.BATTERY_PLUGGED_USB;
} else if ("ac".equals(args[2])) {
val = BatteryManager.BATTERY_PLUGGED_AC;
- }
- else {
+ } else if ("wireless".equals(args[2])) {
+ val = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ } else {
break fail;
}
IPowerManager pm