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

Commit 0c5001d7 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add APIs to remove tasks.

You can remove sub-tasks inside of a task, or an entire task.

When removing an entire task, you can have its process killed
as well.

When the process is killed, any running services will get an
onTaskRemoved() callback for them to do cleanup before their
process is killed (and the service possibly restarted).

Or they can set a new android:stopWithTask attribute to just
have the service automatically (cleanly) stopped at this point.

Change-Id: I1891bc2da006fa53b99c52f9040f1145650e6808
parent 26b05f7d
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ package android {
    field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
    field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
    field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
    field public static final java.lang.String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
    field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
    field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
@@ -855,6 +856,7 @@ package android {
    field public static final int state_window_focused = 16842909; // 0x101009d
    field public static final int staticWallpaperPreview = 16843569; // 0x1010331
    field public static final int stepSize = 16843078; // 0x1010146
    field public static final int stopWithTask = 16843623; // 0x1010367
    field public static final int streamType = 16843273; // 0x1010209
    field public static final int stretchColumns = 16843081; // 0x1010149
    field public static final int stretchMode = 16843030; // 0x1010116
@@ -929,9 +931,9 @@ package android {
    field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
    field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
    field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
    field public static final int textEditSuggestionItemLayout = 16843626; // 0x101036a
    field public static final int textEditSuggestionsBottomWindowLayout = 16843624; // 0x1010368
    field public static final int textEditSuggestionsTopWindowLayout = 16843625; // 0x1010369
    field public static final int textEditSuggestionItemLayout = 16843627; // 0x101036b
    field public static final int textEditSuggestionsBottomWindowLayout = 16843625; // 0x1010369
    field public static final int textEditSuggestionsTopWindowLayout = 16843626; // 0x101036a
    field public static final int textFilterEnabled = 16843007; // 0x10100ff
    field public static final int textIsSelectable = 16843542; // 0x1010316
    field public static final int textOff = 16843045; // 0x1010125
@@ -943,7 +945,7 @@ package android {
    field public static final int textSelectHandleWindowStyle = 16843464; // 0x10102c8
    field public static final int textSize = 16842901; // 0x1010095
    field public static final int textStyle = 16842903; // 0x1010097
    field public static final int textSuggestionsWindowStyle = 16843623; // 0x1010367
    field public static final int textSuggestionsWindowStyle = 16843624; // 0x1010368
    field public static final int textViewStyle = 16842884; // 0x1010084
    field public static final int theme = 16842752; // 0x1010000
    field public static final int thickness = 16843360; // 0x1010260
@@ -3384,6 +3386,7 @@ package android.app {
    method public void onRebind(android.content.Intent);
    method public deprecated void onStart(android.content.Intent, int);
    method public int onStartCommand(android.content.Intent, int, int);
    method public void onTaskRemoved(android.content.Intent);
    method public boolean onUnbind(android.content.Intent);
    method public final void startForeground(int, android.app.Notification);
    method public final void stopForeground(boolean);
@@ -5840,6 +5843,8 @@ package android.content.pm {
    method public int describeContents();
    method public void dump(android.util.Printer, java.lang.String);
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
    field public int flags;
    field public java.lang.String permission;
  }
+50 −11
Original line number Diff line number Diff line
@@ -204,13 +204,6 @@ public class ActivityManager {
     */
    public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;

    /**
     * Flag for use with {@link #getRecentTasks}: also return the thumbnail
     * bitmap (if available) for each recent task.
     * @hide
     */
    public static final int TASKS_GET_THUMBNAILS = 0x0001000;
    
    /**
     * Return a list of the tasks that the user has recently launched, with
     * the most recent being first and older ones after in order.
@@ -241,7 +234,7 @@ public class ActivityManager {
    /**
     * Information you can retrieve about a particular task that is currently
     * "running" in the system.  Note that a running task does not mean the
     * given task actual has a process it is actively running in; it simply
     * given task actually has a process it is actively running in; it simply
     * means that the user has gone to it and never closed it, but currently
     * the system may have killed its process and is only holding on to its
     * last state in order to restart it when the user returns.
@@ -396,6 +389,55 @@ public class ActivityManager {
        return getRunningTasks(maxNum, 0, null);
    }

    /**
     * Remove some end of a task's activity stack that is not part of
     * the main application.  The selected activities will be finished, so
     * they are no longer part of the main task.
     *
     * @param taskId The identifier of the task.
     * @param subTaskIndex The number of the sub-task; this corresponds
     * to the index of the thumbnail returned by {@link #getTaskThumbnails(int)}.
     * @return Returns true if the sub-task was found and was removed.
     *
     * @hide
     */
    public boolean removeSubTask(int taskId, int subTaskIndex)
            throws SecurityException {
        try {
            return ActivityManagerNative.getDefault().removeSubTask(taskId, subTaskIndex);
        } catch (RemoteException e) {
            // System dead, we will be dead too soon!
            return false;
        }
    }

    /**
     * If set, the process of the root activity of the task will be killed
     * as part of removing the task.
     * @hide
     */
    public static final int REMOVE_TASK_KILL_PROCESS = 0x0001;

    /**
     * Completely remove the given task.
     *
     * @param taskId Identifier of the task to be removed.
     * @param flags Additional operational flags.  May be 0 or
     * {@link #REMOVE_TASK_KILL_PROCESS}.
     * @return Returns true if the given task was found and removed.
     *
     * @hide
     */
    public boolean removeTask(int taskId, int flags)
            throws SecurityException {
        try {
            return ActivityManagerNative.getDefault().removeTask(taskId, flags);
        } catch (RemoteException e) {
            // System dead, we will be dead too soon!
            return false;
        }
    }

    /** @hide */
    public static class TaskThumbnails implements Parcelable {
        public Bitmap mainThumbnail;
@@ -405,9 +447,6 @@ public class ActivityManager {
        /** @hide */
        public IThumbnailRetriever retriever;

        /** @hide Magic for ActivityManagerService.  Not marshalled */
        public ArrayList<Bitmap> otherThumbnails;

        public TaskThumbnails() {
        }

+50 −0
Original line number Diff line number Diff line
@@ -1406,6 +1406,28 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }
        
        case REMOVE_SUB_TASK_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            int taskId = data.readInt();
            int subTaskIndex = data.readInt();
            boolean result = removeSubTask(taskId, subTaskIndex);
            reply.writeNoException();
            reply.writeInt(result ? 1 : 0);
            return true;
        }

        case REMOVE_TASK_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            int taskId = data.readInt();
            int fl = data.readInt();
            boolean result = removeTask(taskId, fl);
            reply.writeNoException();
            reply.writeInt(result ? 1 : 0);
            return true;
        }

        }

        return super.onTransact(code, data, reply, flags);
@@ -3163,5 +3185,33 @@ class ActivityManagerProxy implements IActivityManager
        return result;
    }
    
    public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(taskId);
        data.writeInt(subTaskIndex);
        mRemote.transact(REMOVE_SUB_TASK_TRANSACTION, data, reply, 0);
        reply.readException();
        boolean result = reply.readInt() != 0;
        reply.recycle();
        data.recycle();
        return result;
    }

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

    private IBinder mRemote;
}
+10 −2
Original line number Diff line number Diff line
@@ -334,6 +334,7 @@ public final class ActivityThread {

    private static final class ServiceArgsData {
        IBinder token;
        boolean taskRemoved;
        int startId;
        int flags;
        Intent args;
@@ -534,10 +535,11 @@ public final class ActivityThread {
            queueOrSendMessage(H.UNBIND_SERVICE, s);
        }

        public final void scheduleServiceArgs(IBinder token, int startId,
        public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags ,Intent args) {
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.taskRemoved = taskRemoved;
            s.startId = startId;
            s.flags = flags;
            s.args = args;
@@ -2129,7 +2131,13 @@ public final class ActivityThread {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                }
                int res = s.onStartCommand(data.args, data.flags, data.startId);
                int res;
                if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }

                QueuedWork.waitToFinish();

+4 −2
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ public abstract class ApplicationThreadNative extends Binder
        {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            boolean taskRemoved = data.readInt() != 0;
            int startId = data.readInt();
            int fl = data.readInt();
            Intent args;
@@ -227,7 +228,7 @@ public abstract class ApplicationThreadNative extends Binder
            } else {
                args = null;
            }
            scheduleServiceArgs(token, startId, fl, args);
            scheduleServiceArgs(token, taskRemoved, startId, fl, args);
            return true;
        }

@@ -688,11 +689,12 @@ class ApplicationThreadProxy implements IApplicationThread {
        data.recycle();
    }

    public final void scheduleServiceArgs(IBinder token, int startId,
    public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
	    int flags, Intent args) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(taskRemoved ? 1 : 0);
        data.writeInt(startId);
        data.writeInt(flags);
        if (args != null) {
Loading