Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 742a6712 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

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
parent 8ca8a69d
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -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;

+42 −0
Original line number Diff line number Diff line
@@ -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];
+6 −0
Original line number Diff line number Diff line
@@ -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)
+4 −0
Original line number Diff line number Diff line
@@ -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);
+44 −16
Original line number Diff line number Diff line
@@ -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:");
Loading