summaryrefslogtreecommitdiffstats
path: root/cmds
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2011-05-04 14:49:28 -0700
committerAmith Yamasani <yamasani@google.com>2012-02-03 12:01:47 -0800
commit742a67127366c376fdf188ff99ba30b27d3bf90c (patch)
tree4a801b0b2e9ee10fb322e3b450e2af9eb6e3002f /cmds
parent8ca8a69d5801ad4b809e7b9dbf53bd728820924b (diff)
downloadframeworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.zip
frameworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.tar.gz
frameworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.tar.bz2
Multi-user - 1st major checkin
Switching activity stacks Cache ContentProvider per user Long-press power to switch users (on phone) Added ServiceMap for separating services by user Launch PendingIntents on the correct user's uid Fix task switching from Recents list AppWidgetService is mostly working. Commands added to pm and am to allow creating and switching profiles. Change-Id: I15810e8cfbe50a04bd3323a7ef5a8ff4230870ed
Diffstat (limited to 'cmds')
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java14
-rw-r--r--cmds/installd/commands.c42
-rw-r--r--cmds/installd/installd.c6
-rw-r--r--cmds/installd/installd.h4
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java60
5 files changed, 109 insertions, 17 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index fddb429..3d36ebf 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -135,6 +136,8 @@ public class Am {
runToUri(false);
} else if (op.equals("to-intent-uri")) {
runToUri(true);
+ } else if (op.equals("switch-profile")) {
+ runSwitchUser();
} else {
throw new IllegalArgumentException("Unknown command: " + op);
}
@@ -531,7 +534,8 @@ public class Am {
Intent intent = makeIntent();
IntentReceiver receiver = new IntentReceiver();
System.out.println("Broadcasting: " + intent);
- mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false);
+ mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false,
+ Binder.getOrigCallingUser());
receiver.waitForFinish();
}
@@ -722,6 +726,14 @@ public class Am {
mAm.setDebugApp(null, false, true);
}
+ private void runSwitchUser() throws Exception {
+ if (android.os.Process.myUid() != 0) {
+ throw new RuntimeException("switchuser can only be run as root");
+ }
+ String user = nextArgRequired();
+ mAm.switchUser(Integer.parseInt(user));
+ }
+
class MyActivityController extends IActivityController.Stub {
final String mGdbPort;
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index dd92bbe..203d180 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -148,6 +148,48 @@ int delete_persona(uid_t persona)
return delete_dir_contents(pkgdir, 1, NULL);
}
+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];
+ DIR *d;
+ struct dirent *de;
+ struct stat s;
+ uid_t uid;
+
+ if (create_persona_path(src_data_dir, src_persona)) {
+ return -1;
+ }
+
+ d = opendir(src_data_dir);
+ if (d != NULL) {
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+ /* Create the full path to the package's data dir */
+ create_pkg_path(pkg_path, name, PKG_DIR_POSTFIX, src_persona);
+ /* Get the file stat */
+ if (stat(pkg_path, &s) < 0) continue;
+ /* Get the uid of the package */
+ ALOGI("Adding datadir for uid = %d\n", s.st_uid);
+ uid = (uid_t) s.st_uid % PER_USER_RANGE;
+ /* Create the directory for the target */
+ make_user_data(name, uid + target_persona * PER_USER_RANGE,
+ target_persona);
+ }
+ }
+ closedir(d);
+ }
+ return 0;
+}
+
int delete_cache(const char *pkgname)
{
char cachedir[PKG_PATH_MAX];
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 569b491..7f94a96 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -107,6 +107,11 @@ static int do_rm_user(char **arg, char reply[REPLY_MAX])
return delete_persona(atoi(arg[0])); /* userid */
}
+static int do_clone_user_data(char **arg, char reply[REPLY_MAX])
+{
+ return clone_persona_data(atoi(arg[0]), atoi(arg[1]), atoi(arg[2]));
+}
+
static int do_movefiles(char **arg, char reply[REPLY_MAX])
{
return movefiles();
@@ -146,6 +151,7 @@ struct cmdinfo cmds[] = {
{ "unlinklib", 1, do_unlinklib },
{ "mkuserdata", 3, do_mk_user_data },
{ "rmuser", 1, do_rm_user },
+ { "cloneuserdata", 3, do_clone_user_data },
};
static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 173cabf..78342bb 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -72,6 +72,9 @@
#define PKG_NAME_MAX 128 /* largest allowed package name */
#define PKG_PATH_MAX 256 /* max size of any path we use */
+#define PER_USER_RANGE ((uid_t)100000) /* range of uids per user
+ uid = persona * PER_USER_RANGE + appid */
+
/* data structures */
typedef struct {
@@ -143,6 +146,7 @@ int renamepkg(const char *oldpkgname, const char *newpkgname);
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 clone_persona_data(uid_t src_persona, uid_t target_persona, int copy);
int delete_cache(const char *pkgname);
int move_dex(const char *src, const char *dst);
int rm_dex(const char *path);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c0ba543..f457842 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -16,8 +16,6 @@
package com.android.commands.pm;
-import com.android.internal.content.PackageHelper;
-
import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
@@ -33,14 +31,17 @@ import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.content.pm.UserInfo;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.Parcel;
+import android.os.Binder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import com.android.internal.content.PackageHelper;
+
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -135,13 +136,18 @@ public final class Pm {
return;
}
- if ("createUser".equals(op)) {
- runCreateUser();
+ if ("create-profile".equals(op)) {
+ runCreateProfile();
+ return;
+ }
+
+ if ("remove-profile".equals(op)) {
+ runRemoveProfile();
return;
}
- if ("removeUser".equals(op)) {
- runRemoveUser();
+ if ("list-profiles".equals(op)) {
+ runListProfiles();
return;
}
@@ -829,10 +835,10 @@ public final class Pm {
}
}
- public void runCreateUser() {
+ public void runCreateProfile() {
// Need to be run as root
if (Process.myUid() != ROOT_UID) {
- System.err.println("Error: createUser must be run as root");
+ System.err.println("Error: create-profile must be run as root");
return;
}
String name;
@@ -845,7 +851,7 @@ public final class Pm {
name = arg;
try {
if (mPm.createUser(name, 0) == null) {
- System.err.println("Error: couldn't create user.");
+ System.err.println("Error: couldn't create profile.");
showUsage();
}
} catch (RemoteException e) {
@@ -855,10 +861,10 @@ public final class Pm {
}
- public void runRemoveUser() {
+ public void runRemoveProfile() {
// Need to be run as root
if (Process.myUid() != ROOT_UID) {
- System.err.println("Error: removeUser must be run as root");
+ System.err.println("Error: remove-profile must be run as root");
return;
}
int userId;
@@ -877,7 +883,7 @@ public final class Pm {
}
try {
if (!mPm.removeUser(userId)) {
- System.err.println("Error: couldn't remove user.");
+ System.err.println("Error: couldn't remove profile.");
showUsage();
}
} catch (RemoteException e) {
@@ -886,6 +892,27 @@ public final class Pm {
}
}
+ public void runListProfiles() {
+ // Need to be run as root
+ if (Process.myUid() != ROOT_UID) {
+ System.err.println("Error: list-profiles must be run as root");
+ return;
+ }
+ try {
+ List<UserInfo> users = mPm.getUsers();
+ if (users == null) {
+ System.err.println("Error: couldn't get users");
+ } else {
+ System.out.println("Users:");
+ for (int i = 0; i < users.size(); i++) {
+ System.out.println("\t" + users.get(i).toString());
+ }
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
boolean finished;
boolean result;
@@ -966,7 +993,8 @@ public final class Pm {
ClearDataObserver obs = new ClearDataObserver();
try {
- if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs)) {
+ if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs,
+ Binder.getOrigCallingUser())) {
System.err.println("Failed");
}
@@ -1132,8 +1160,8 @@ public final class Pm {
System.err.println(" pm disable-user PACKAGE_OR_COMPONENT");
System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
System.err.println(" pm get-install-location");
- System.err.println(" pm createUser USER_NAME");
- System.err.println(" pm removeUser USER_ID");
+ System.err.println(" pm create-profile USER_NAME");
+ System.err.println(" pm remove-profile USER_ID");
System.err.println("");
System.err.println("pm list packages: prints all packages, optionally only");
System.err.println(" those whose package name contains the text in FILTER. Options:");