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

Commit 5e03e2ca authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

More multi-user stuff:

- New (hidden) isUserRunning() API.
- Maintain LRU list of visited users.
- New FLAG_IS_DATA_ONLY for ApplicationInfo.
- Clean up pending intent records when force-stopping a user (or package).
  (Also fixes bug #6880627: PendingIntent.getService() returns stale
  intent of force stopped app)
- Fix force-stopping when installing an app to do the force-stop across
  all users for that app.
- When selecting which processes to kill during a force stop, do this
  based on the actual packages loaded in the process, not just process
  name matching.
- You can now use --user option in am when starting activities, services,
  and instrumentation.
- The am --user option accepts "current" and "all" as arguments.
- The pm uninstall command now uninstalls for all users, so it matches
  the semantics of the install command.
- PhoneWindowManager now explicitly says to start home in the current
  user.
- Activity manager call to retrieve the MIME type from a content provider
  now takes a user argument, so it will direct this to the proper user.
- The package manager uninstall paths are now implemented around
  PackageSetting, not PackageParser.Package.  This allows them to work
  even if the application's apk has been removed (in which case it only
  exists as a PackageSetting, not the PackageParser.Package parsed from
  the apk).

Change-Id: I3522f6fcf32603090bd6e01cc90ce70b6c5aae40
parent 970683c5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6327,6 +6327,7 @@ package android.content.pm {
    field public static final int FLAG_FACTORY_TEST = 16; // 0x10
    field public static final int FLAG_HAS_CODE = 4; // 0x4
    field public static final int FLAG_INSTALLED = 8388608; // 0x800000
    field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000
    field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
    field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
    field public static final int FLAG_PERSISTENT = 8; // 0x8
+40 −7
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.AndroidException;
import android.view.Display;
import android.view.IWindowManager;
@@ -147,6 +148,18 @@ public class Am {
        }
    }

    int parseUserArg(String arg) {
        int userId;
        if ("all".equals(arg)) {
            userId = UserHandle.USER_ALL;
        } else if ("current".equals(arg) || "cur".equals(arg)) {
            userId = UserHandle.USER_CURRENT;
        } else {
            userId = Integer.parseInt(arg);
        }
        return userId;
    }

    private Intent makeIntent() throws URISyntaxException {
        Intent intent = new Intent();
        Intent baseIntent = intent;
@@ -321,7 +334,7 @@ public class Am {
            } else if (opt.equals("--opengl-trace")) {
                mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
            } else if (opt.equals("--user")) {
                mUserId = Integer.parseInt(nextArgRequired());
                mUserId = parseUserArg(nextArgRequired());
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return null;
@@ -392,8 +405,12 @@ public class Am {

    private void runStartService() throws Exception {
        Intent intent = makeIntent();
        if (mUserId == UserHandle.USER_ALL) {
            System.err.println("Error: Can't start activity with user 'all'");
            return;
        }
        System.out.println("Starting service: " + intent);
        ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
        ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
        if (cn == null) {
            System.err.println("Error: Not found; no service started.");
        }
@@ -402,10 +419,15 @@ public class Am {
    private void runStart() throws Exception {
        Intent intent = makeIntent();

        if (mUserId == UserHandle.USER_ALL) {
            System.err.println("Error: Can't start service with user 'all'");
            return;
        }

        String mimeType = intent.getType();
        if (mimeType == null && intent.getData() != null
                && "content".equals(intent.getData().getScheme())) {
            mimeType = mAm.getProviderMimeType(intent.getData());
            mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
        }

        do {
@@ -460,11 +482,11 @@ public class Am {
            int res;
            if (mWaitOption) {
                result = mAm.startActivityAndWait(null, intent, mimeType,
                            null, null, 0, mStartFlags, mProfileFile, fd, null);
                            null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
                res = result.result;
            } else {
                res = mAm.startActivity(null, intent, mimeType,
                        null, null, 0, mStartFlags, mProfileFile, fd, null);
                res = mAm.startActivityAsUser(null, intent, mimeType,
                        null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
            }
            PrintStream out = mWaitOption ? System.out : System.err;
            boolean launched = false;
@@ -573,6 +595,7 @@ public class Am {
        boolean wait = false;
        boolean rawMode = false;
        boolean no_window_animation = false;
        int userId = 0;
        Bundle args = new Bundle();
        String argKey = null, argValue = null;
        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -592,12 +615,19 @@ public class Am {
            } else if (opt.equals("--no_window_animation")
                    || opt.equals("--no-window-animation")) {
                no_window_animation = true;
            } else if (opt.equals("--user")) {
                userId = parseUserArg(nextArgRequired());
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return;
            }
        }

        if (userId == UserHandle.USER_ALL) {
            System.err.println("Error: Can't start instrumentation with user 'all'");
            return;
        }

        String cnArg = nextArgRequired();
        ComponentName cn = ComponentName.unflattenFromString(cnArg);
        if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
@@ -614,7 +644,7 @@ public class Am {
            wm.setAnimationScale(1, 0.0f);
        }

        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, userId)) {
            throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
        }

@@ -1338,6 +1368,7 @@ public class Am {
                "       am kill-all\n" +
                "       am broadcast <INTENT>\n" +
                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
                "               [--user <USER_ID> | all | current]\n" +
                "               [--no-window-animation] <COMPONENT>\n" +
                "       am profile start <PROCESS> <FILE>\n" +
                "       am profile stop [<PROCESS>]\n" +
@@ -1384,6 +1415,7 @@ public class Am {
                "    -p <FILE>: write profiling data to <FILE>\n" +
                "    -w: wait for instrumentation to finish before returning.  Required for\n" +
                "        test runners.\n" +
                "    --user [<USER_ID> | all | current]: Specify user instrumentation runs in.\n" +
                "    --no-window-animation: turn off window animations will running.\n" +
                "\n" +
                "am profile: start and stop profiler on a process.\n" +
@@ -1431,6 +1463,7 @@ public class Am {
                "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
                "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
                "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
                "    [--user [<USER_ID> | all | current]\n" +
                "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
                "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
                "    [--include-stopped-packages]\n" +
+9 −9
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import com.android.internal.content.PackageHelper;

import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
@@ -40,12 +39,9 @@ import android.content.pm.VerificationParams;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Binder;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserManager;

import java.io.File;
import java.lang.reflect.Field;
@@ -74,7 +70,6 @@ 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);
@@ -1054,11 +1049,16 @@ public final class Pm {
    }

    private void runUninstall() {
        int unInstallFlags = 0;
        int unInstallFlags = PackageManager.DELETE_ALL_USERS;

        String opt = nextOption();
        if (opt != null && opt.equals("-k")) {
            unInstallFlags = PackageManager.DELETE_KEEP_DATA;
        String opt;
        while ((opt=nextOption()) != null) {
            if (opt.equals("-k")) {
                unInstallFlags |= PackageManager.DELETE_KEEP_DATA;
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return;
            }
        }

        String pkg = nextArg();
+17 −0
Original line number Diff line number Diff line
@@ -1957,4 +1957,21 @@ public class ActivityManager {
            return false;
        }
    }

    /**
     * Return whether the given user is actively running.  This means that
     * the user is in the "started" state, not "stopped" -- it is currently
     * allowed to run code through scheduled alarms, receiving broadcasts,
     * etc.  A started user may be either the current foreground user or a
     * background user; the result here does not distinguish between the two.
     * @param userid the user's id. Zero indicates the default user.
     * @hide
     */
    public boolean isUserRunning(int userid) {
        try {
            return ActivityManagerNative.getDefault().isUserRunning(userid);
        } catch (RemoteException e) {
            return false;
        }
    }
}
+40 −13
Original line number Diff line number Diff line
@@ -177,9 +177,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
                    ? data.readFileDescriptor() : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int userId = data.readInt();
            WaitResult result = startActivityAndWait(app, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags,
                    profileFile, profileFd, options);
                    profileFile, profileFd, options, userId);
            reply.writeNoException();
            result.writeToParcel(reply, 0);
            return true;
@@ -811,7 +812,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            Bundle arguments = data.readBundle();
            IBinder b = data.readStrongBinder();
            IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
            boolean res = startInstrumentation(className, profileFile, fl, arguments, w);
            int userId = data.readInt();
            boolean res = startInstrumentation(className, profileFile, fl, arguments, w, userId);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
@@ -1323,11 +1325,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }
        
        case KILL_APPLICATION_WITH_UID_TRANSACTION: {
        case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            String pkg = data.readString();
            int uid = data.readInt();
            killApplicationWithUid(pkg, uid);
            int appid = data.readInt();
            killApplicationWithAppId(pkg, appid);
            reply.writeNoException();
            return true;
        }
@@ -1424,7 +1426,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
        case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            Uri uri = Uri.CREATOR.createFromParcel(data);
            String type = getProviderMimeType(uri);
            int userId = data.readInt();
            String type = getProviderMimeType(uri, userId);
            reply.writeNoException();
            reply.writeString(type);
            return true;
@@ -1573,6 +1576,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case IS_USER_RUNNING_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            int userid = data.readInt();
            boolean result = isUserRunning(userid);
            reply.writeNoException();
            reply.writeInt(result ? 1 : 0);
            return true;
        }

        case REMOVE_SUB_TASK_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
@@ -1827,7 +1839,7 @@ class ActivityManagerProxy implements IActivityManager
    public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1851,6 +1863,7 @@ class ActivityManagerProxy implements IActivityManager
        } else {
            data.writeInt(0);
        }
        data.writeInt(userId);
        mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
        reply.readException();
        WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
@@ -2719,7 +2732,7 @@ class ActivityManagerProxy implements IActivityManager
    }

    public boolean startInstrumentation(ComponentName className, String profileFile,
            int flags, Bundle arguments, IInstrumentationWatcher watcher)
            int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
@@ -2729,6 +2742,7 @@ class ActivityManagerProxy implements IActivityManager
        data.writeInt(flags);
        data.writeBundle(arguments);
        data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
        data.writeInt(userId);
        mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
        reply.readException();
        boolean res = reply.readInt() != 0;
@@ -3366,13 +3380,13 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
    }
    
    public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
    public void killApplicationWithAppId(String pkg, int appid) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeString(pkg);
        data.writeInt(uid);
        mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0);
        data.writeInt(appid);
        mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
@@ -3507,12 +3521,12 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    public String getProviderMimeType(Uri uri)
            throws RemoteException {
    public String getProviderMimeType(Uri uri, int userId) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        uri.writeToParcel(data, 0);
        data.writeInt(userId);
        mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
        reply.readException();
        String res = reply.readString();
@@ -3747,6 +3761,19 @@ class ActivityManagerProxy implements IActivityManager
        return userInfo;
    }

    public boolean isUserRunning(int userid) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(userid);
        mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
        reply.readException();
        boolean result = reply.readInt() != 0;
        reply.recycle();
        data.recycle();
        return result;
    }

    public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
Loading