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

Commit 421a1dd1 authored by Craig Mautner's avatar Craig Mautner Committed by Android (Google) Code Review
Browse files

Merge "Launch new tasks with Doc Centric flag."

parents dbcd5b70 d00f4740
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6849,6 +6849,7 @@ package android.content {
    field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
    field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
    field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
    field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 268959744; // 0x10080000
    field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
    field public static final int FLAG_ACTIVITY_NO_ANIMATION = 65536; // 0x10000
    field public static final int FLAG_ACTIVITY_NO_HISTORY = 1073741824; // 0x40000000
+52 −3
Original line number Diff line number Diff line
@@ -3457,7 +3457,16 @@ public class Intent implements Parcelable, Cloneable {
     */
    public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
    /**
     * <strong>Do not use this flag unless you are implementing your own
     * This flag is used to create a new task and launch an activity into it.
     * This flag is always paired with either {@link #FLAG_ACTIVITY_NEW_DOCUMENT}
     * or {@link #FLAG_ACTIVITY_NEW_TASK}. In both cases these flags alone would
     * search through existing tasks for ones matching this Intent. Only if no such
     * task is found would a new task be created. When paired with
     * FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors are modified to skip
     * the search for a matching task and unconditionally start a new task.
     *
     * <strong>When used with {@link #FLAG_ACTIVITY_NEW_TASK} do not use this
     * flag unless you are implementing your own
     * top-level application launcher.</strong>  Used in conjunction with
     * {@link #FLAG_ACTIVITY_NEW_TASK} to disable the
     * behavior of bringing an existing task to the foreground.  When set,
@@ -3469,12 +3478,18 @@ public class Intent implements Parcelable, Cloneable {
     * you should not use this flag unless you provide some way for a user to
     * return back to the tasks you have launched.</strong>
     *
     * <p>This flag is ignored if
     * {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
     * See {@link #FLAG_ACTIVITY_NEW_DOCUMENT} for details of this flag's use for
     * creating new document tasks.
     *
     * <p>This flag is ignored if one of {@link #FLAG_ACTIVITY_NEW_TASK} or
     * {@link #FLAG_ACTIVITY_NEW_TASK} is not also set.
     *
     * <p>See
     * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
     * Stack</a> for more information about tasks.
     *
     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
     * @see #FLAG_ACTIVITY_NEW_TASK
     */
    public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;
    /**
@@ -3580,6 +3595,34 @@ public class Intent implements Parcelable, Cloneable {
     * to mail.
     */
    public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000;
    /**
     * This flag is used to break out "documents" into separate tasks that can
     * be reached via the Recents mechanism. Such a document is any kind of
     * item for which an application may want to maintain multiple simultaneous
     * instances. Examples might be text files, web pages, spreadsheets, or
     * emails. Each such document will be in a separate task in the Recents list.
     *
     * <p>When set, the activity specified by this Intent will launch into a
     * separate task rooted at that activity. The activity launched must be
     * defined with {@link android.R.attr#launchMode} "standard" or "singleTop".
     *
     * <p>If FLAG_ACTIVITY_NEW_DOCUMENT is used without
     * {@link #FLAG_ACTIVITY_MULTIPLE_TASK} then the activity manager will
     * search for an existing task with a matching target activity and Intent
     * data URI and relaunch that task, first finishing all activities down to
     * the root activity and then calling the root activity's
     * {@link android.app.Activity#onNewIntent(Intent)} method. If no existing
     * task's root activity matches the Intent's data URI then a new task will
     * be launched with the target activity as root.
     *
     * <p>When paired with {@link #FLAG_ACTIVITY_MULTIPLE_TASK} this will
     * always create a new task. Thus the same document may be made to appear
     * more than one time in Recents.
     *
     * @see #FLAG_ACTIVITY_MULTIPLE_TASK
     */
    public static final int FLAG_ACTIVITY_NEW_DOCUMENT =
            FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | FLAG_ACTIVITY_NEW_TASK;
    /**
     * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint}
     * callback from occurring on the current frontmost activity before it is
@@ -6246,6 +6289,7 @@ public class Intent implements Parcelable, Cloneable {
     * @see #FLAG_ACTIVITY_FORWARD_RESULT
     * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
     * @see #FLAG_ACTIVITY_MULTIPLE_TASK
     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
     * @see #FLAG_ACTIVITY_NEW_TASK
     * @see #FLAG_ACTIVITY_NO_ANIMATION
     * @see #FLAG_ACTIVITY_NO_HISTORY
@@ -7342,4 +7386,9 @@ public class Intent implements Parcelable, Cloneable {
        String htmlText = htmlTexts != null ? htmlTexts.get(which) : null;
        return new ClipData.Item(text, htmlText, null, uri);
    }

    /** @hide */
    public boolean isDocument() {
        return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT;
    }
}
+26 −11
Original line number Diff line number Diff line
@@ -3319,11 +3319,27 @@ public final class ActivityManagerService extends ActivityManagerNative
            return;
        }
        // Remove any existing entries that are the same kind of task.
        final Intent intent = task.intent;
        final boolean document = intent != null && intent.isDocument();
        for (int i=0; i<N; i++) {
            TaskRecord tr = mRecentTasks.get(i);
            if (task.userId == tr.userId
                    && ((task.affinity != null && task.affinity.equals(tr.affinity))
                    || (task.intent != null && task.intent.filterEquals(tr.intent)))) {
            if (task != tr) {
                if (task.userId != tr.userId) {
                    continue;
                }
                final Intent trIntent = tr.intent;
                if ((task.affinity == null || !task.affinity.equals(tr.affinity)) &&
                    (intent == null || !intent.filterEquals(trIntent))) {
                    continue;
                }
                if (document || trIntent != null && trIntent.isDocument()) {
                    // Document tasks do not match other tasks.
                    continue;
                }
            }
            // Either task and tr are the same or, their affinities match or their intents match
            // and neither of them is a document.
            tr.disposeThumbnail();
            mRecentTasks.remove(i);
            i--;
@@ -3334,7 +3350,6 @@ public final class ActivityManagerService extends ActivityManagerNative
                task = tr;
            }
        }
        }
        if (N >= MAX_RECENT_TASKS) {
            mRecentTasks.remove(N-1).disposeThumbnail();
        }
+28 −16
Original line number Diff line number Diff line
@@ -492,6 +492,9 @@ final class ActivityStack {
            cls = new ComponentName(info.packageName, info.targetActivity);
        }
        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
        boolean isDocument = intent != null & intent.isDocument();
        // If documentData is non-null then it must match the existing task data.
        Uri documentData = isDocument ? intent.getData() : null;

        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -508,23 +511,39 @@ final class ActivityStack {
                continue;
            }

            final Intent taskIntent = task.intent;
            final Intent affinityIntent = task.affinityIntent;
            final boolean taskIsDocument;
            final Uri taskDocumentData;
            if (taskIntent != null && taskIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = taskIntent.getData();
            } else if (affinityIntent != null && affinityIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = affinityIntent.getData();
            } else {
                taskIsDocument = false;
                taskDocumentData = null;
            }

            if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
                    + r.task.intent.getComponent().flattenToShortString()
                    + taskIntent.getComponent().flattenToShortString()
                    + "/aff=" + r.task.affinity + " to new cls="
                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
            if (task.affinity != null) {
                if (task.affinity.equals(info.taskAffinity)) {
            if (!isDocument && !taskIsDocument && task.affinity != null) {
                if (task.affinity.equals(target.taskAffinity)) {
                    if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
                    return r;
                }
            } else if (task.intent != null && task.intent.getComponent().equals(cls)) {
            } else if (taskIntent != null && taskIntent.getComponent().equals(cls) &&
                    Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
                        + r.intent);
                return r;
            } else if (task.affinityIntent != null
                    && task.affinityIntent.getComponent().equals(cls)) {
            } else if (affinityIntent != null && affinityIntent.getComponent().equals(cls) &&
                    Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
@@ -2006,14 +2025,7 @@ final class ActivityStack {
                            + " out to new task " + target.task);
                }

                if (clearWhenTaskReset) {
                    // This is the start of a new sub-task.
                    if (target.thumbHolder == null) {
                        target.thumbHolder = new ThumbnailHolder();
                    }
                } else {
                target.thumbHolder = newThumbHolder;
                }

                final int targetTaskId = targetTask.taskId;
                mWindowManager.setAppGroupId(target.appToken, targetTaskId);
+13 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.am;

import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -1443,6 +1444,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            }
        }

        final boolean newDocument = intent.isDocument();
        if (sourceRecord == null) {
            // This activity is not being started from another...  in this
            // case we -always- start a new task.
@@ -1451,6 +1453,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        } else if (newDocument) {
            if (r.launchMode != ActivityInfo.LAUNCH_MULTIPLE) {
                Slog.w(TAG, "FLAG_ACTIVITY_NEW_DOCUMENT and launchMode != \"standard\"");
                r.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
            }
        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            // The original activity who is starting us is running as a single
            // instance...  this new activity it is starting must go on its