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

Commit fb8dad4f authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Provide alternative find-task method without ActivityRecord"

parents 7b4904bd 4bce80f1
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -49,12 +49,6 @@
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "-2062338592": {
      "message": "Looking for task of %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_TASKS",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "-2054442123": {
      "message": "Setting Intent of %s to %s",
      "level": "VERBOSE",
@@ -475,6 +469,12 @@
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/Transition.java"
    },
    "-1559645910": {
      "message": "Looking for task of type=%s, taskAffinity=%s, intent=%s, info=%s, preferredTDA=%s",
      "level": "DEBUG",
      "group": "WM_DEBUG_TASKS",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "-1558137010": {
      "message": "Config is relaunching invisible activity %s called by %s",
      "level": "VERBOSE",
@@ -1531,6 +1531,12 @@
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "-373110070": {
      "message": "Skipping task: (mismatch activity\/task) %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_TASKS",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "-354571697": {
      "message": "Existence Changed in transition %d: %s",
      "level": "VERBOSE",
+4 −7
Original line number Diff line number Diff line
@@ -547,19 +547,16 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
        return activityType == ACTIVITY_TYPE_STANDARD || activityType == ACTIVITY_TYPE_UNDEFINED;
    }

    public boolean hasCompatibleActivityType(ConfigurationContainer other) {
        /*@WindowConfiguration.ActivityType*/ int thisType = getActivityType();
        /*@WindowConfiguration.ActivityType*/ int otherType = other.getActivityType();

        if (thisType == otherType) {
    public static boolean isCompatibleActivityType(int currentType, int otherType) {
        if (currentType == otherType) {
            return true;
        }
        if (thisType == ACTIVITY_TYPE_ASSISTANT) {
        if (currentType == ACTIVITY_TYPE_ASSISTANT) {
            // Assistant activities are only compatible with themselves...
            return false;
        }
        // Otherwise we are compatible if us or other is not currently defined.
        return thisType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
        return currentType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
    }

    /**
+66 −55
Original line number Diff line number Diff line
@@ -306,52 +306,54 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();

    static class FindTaskResult implements Function<Task, Boolean> {
        ActivityRecord mRecord;
        boolean mIdealMatch;
        ActivityRecord mIdealRecord;
        ActivityRecord mCandidateRecord;

        private ActivityRecord mTarget;
        private Intent intent;
        private ActivityInfo info;
        private int mActivityType;
        private String mTaskAffinity;
        private Intent mIntent;
        private ActivityInfo mInfo;
        private ComponentName cls;
        private int userId;
        private boolean isDocument;
        private Uri documentData;

        void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info) {
            mActivityType = activityType;
            mTaskAffinity = taskAffinity;
            mIntent = intent;
            mInfo = info;
            mIdealRecord = null;
            mCandidateRecord = null;
        }

        /**
         * Returns the top activity in any existing task matching the given Intent in the input
         * result. Returns null if no such task is found.
         */
        void process(ActivityRecord target, Task parent) {
            mTarget = target;

            intent = target.intent;
            info = target.info;
            cls = intent.getComponent();
            if (info.targetActivity != null) {
                cls = new ComponentName(info.packageName, info.targetActivity);
        void process(WindowContainer parent) {
            cls = mIntent.getComponent();
            if (mInfo.targetActivity != null) {
                cls = new ComponentName(mInfo.packageName, mInfo.targetActivity);
            }
            userId = UserHandle.getUserId(info.applicationInfo.uid);
            isDocument = intent != null & intent.isDocument();
            userId = UserHandle.getUserId(mInfo.applicationInfo.uid);
            isDocument = mIntent != null & mIntent.isDocument();
            // If documentData is non-null then it must match the existing task data.
            documentData = isDocument ? intent.getData() : null;
            documentData = isDocument ? mIntent.getData() : null;

            ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", target,
            ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", mInfo,
                    parent);
            parent.forAllLeafTasks(this);
        }

        void clear() {
            mRecord = null;
            mIdealMatch = false;
        }

        void setTo(FindTaskResult result) {
            mRecord = result.mRecord;
            mIdealMatch = result.mIdealMatch;
        }

        @Override
        public Boolean apply(Task task) {
            if (!ConfigurationContainer.isCompatibleActivityType(mActivityType,
                    task.getActivityType())) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping task: (mismatch activity/task) %s", task);
                return false;
            }

            if (task.voiceSession != null) {
                // We never match voice sessions; those always run independently.
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task);
@@ -370,7 +372,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
                return false;
            }
            if (!r.hasCompatibleActivityType(mTarget)) {
            if (!ConfigurationContainer.isCompatibleActivityType(r.getActivityType(),
                    mActivityType)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task);
                return false;
            }
@@ -391,35 +394,33 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            }

            ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
                    r.getTask().rootAffinity, intent.getComponent().flattenToShortString(),
                    info.taskAffinity, (task.realActivity != null
                    r.getTask().rootAffinity, mIntent.getComponent().flattenToShortString(),
                    mInfo.taskAffinity, (task.realActivity != null
                            ? task.realActivity.flattenToShortString() : ""));
            // TODO Refactor to remove duplications. Check if logic can be simplified.
            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
                    && Objects.equals(documentData, taskDocumentData)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
                //dump();
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
                mRecord = r;
                mIdealMatch = true;
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
                mIdealRecord = r;
                return true;
            } else if (affinityIntent != null && affinityIntent.getComponent() != null
                    && affinityIntent.getComponent().compareTo(cls) == 0 &&
                    Objects.equals(documentData, taskDocumentData)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
                mRecord = r;
                mIdealMatch = true;
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
                mIdealRecord = r;
                return true;
            } else if (!isDocument && !taskIsDocument
                    && mRecord == null && task.rootAffinity != null) {
                if (task.rootAffinity.equals(mTarget.taskAffinity)) {
                    && mIdealRecord == null && mCandidateRecord == null
                    && task.rootAffinity != null) {
                if (task.rootAffinity.equals(mTaskAffinity)) {
                    ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
                    // It is possible for multiple tasks to have the same root affinity especially
                    // if they are in separate stacks. We save off this candidate, but keep looking
                    // to see if there is a better candidate.
                    mRecord = r;
                    mIdealMatch = false;
                    mCandidateRecord = r;
                }
            } else {
                ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task);
@@ -2238,38 +2239,48 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

    @Nullable
    ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea) {
        ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s", r);
        mTmpFindTaskResult.clear();
        return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info,
                preferredTaskDisplayArea);
    }

    @Nullable
    ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info,
            TaskDisplayArea preferredTaskDisplayArea) {
        ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s"
                        + ", info=%s, preferredTDA=%s", activityType, taskAffinity, intent, info,
                preferredTaskDisplayArea);
        mTmpFindTaskResult.init(activityType, taskAffinity, intent, info);

        // Looking up task on preferred display area first
        ActivityRecord candidateActivity = null;
        if (preferredTaskDisplayArea != null) {
            preferredTaskDisplayArea.findTaskLocked(r, true /* isPreferredDisplay */,
                    mTmpFindTaskResult);
            if (mTmpFindTaskResult.mIdealMatch) {
                return mTmpFindTaskResult.mRecord;
            mTmpFindTaskResult.process(preferredTaskDisplayArea);
            if (mTmpFindTaskResult.mIdealRecord != null) {
                return mTmpFindTaskResult.mIdealRecord;
            } else if (mTmpFindTaskResult.mCandidateRecord != null) {
                candidateActivity = mTmpFindTaskResult.mCandidateRecord;
            }
        }

        final ActivityRecord task = getItemFromTaskDisplayAreas(taskDisplayArea -> {
        final ActivityRecord idealMatchActivity = getItemFromTaskDisplayAreas(taskDisplayArea -> {
            if (taskDisplayArea == preferredTaskDisplayArea) {
                return null;
            }

            taskDisplayArea.findTaskLocked(r, false /* isPreferredDisplay */,
                    mTmpFindTaskResult);
            if (mTmpFindTaskResult.mIdealMatch) {
                return mTmpFindTaskResult.mRecord;
            mTmpFindTaskResult.process(taskDisplayArea);
            if (mTmpFindTaskResult.mIdealRecord != null) {
                return mTmpFindTaskResult.mIdealRecord;
            }
            return null;
        });
        if (task != null) {
            return task;
        if (idealMatchActivity != null) {
            return idealMatchActivity;
        }

        if (WM_DEBUG_TASKS.isEnabled() && mTmpFindTaskResult.mRecord == null) {
        if (WM_DEBUG_TASKS.isEnabled() && candidateActivity == null) {
            ProtoLog.d(WM_DEBUG_TASKS, "No task found");
        }
        return mTmpFindTaskResult.mRecord;
        return candidateActivity;
    }

    /**
+0 −41
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
import static com.android.server.wm.Task.ActivityState.RESUMED;
@@ -128,9 +127,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
     */
    Task mPreferredTopFocusableRootTask;

    private final RootWindowContainer.FindTaskResult
            mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();

    /**
     * If this is the same as {@link #getFocusedRootTask} then the activity on the top of the
     * focused root task has been resumed. If root tasks are changing position this will hold the
@@ -1312,43 +1308,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
        return someActivityPaused[0] > 0;
    }

    /**
     * Find task for putting the Activity in.
     */
    void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
            RootWindowContainer.FindTaskResult result) {
        mTmpFindTaskResult.clear();
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final Task rootTask = mChildren.get(i).asTask();
            if (rootTask == null) {
                continue;
            }
            if (!r.hasCompatibleActivityType(rootTask) && rootTask.isLeafTask()) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping rootTask: (mismatch activity/rootTask) "
                        + "%s", rootTask);
                continue;
            }

            mTmpFindTaskResult.process(r, rootTask);
            // It is possible to have tasks in multiple root tasks with the same root affinity, so
            // we should keep looking after finding an affinity match to see if there is a
            // better match in another root task. Also, task affinity isn't a good enough reason
            // to target a display which isn't the source of the intent, so skip any affinity
            // matches not on the specified display.
            if (mTmpFindTaskResult.mRecord != null) {
                if (mTmpFindTaskResult.mIdealMatch) {
                    result.setTo(mTmpFindTaskResult);
                    return;
                } else if (isPreferredDisplayArea) {
                    // Note: since the traversing through the root tasks is top down, the floating
                    // tasks should always have lower priority than any affinity-matching tasks
                    // in the fullscreen root tasks
                    result.setTo(mTmpFindTaskResult);
                }
            }
        }
    }

    void onSplitScreenModeDismissed() {
        // The focused task could be a non-resizeable fullscreen root task that is on top of the
        // other split-screen tasks, therefore had to dismiss split-screen, make sure the current
+9 −6
Original line number Diff line number Diff line
@@ -314,11 +314,12 @@ public class ActivityStackTests extends WindowTestsBase {

        final RootWindowContainer.FindTaskResult result =
                new RootWindowContainer.FindTaskResult();
        result.process(r, task);
        result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info);
        result.process(task);

        assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
        assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */));
        assertNotNull(result.mRecord);
        assertNotNull(result.mIdealRecord);
    }

    @Test
@@ -340,15 +341,17 @@ public class ActivityStackTests extends WindowTestsBase {
        final ActivityRecord r1 = new ActivityBuilder(mAtm).setComponent(
                target).setTargetActivity(targetActivity).build();
        RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult();
        result.process(r1, parentTask);
        assertThat(result.mRecord).isNotNull();
        result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info);
        result.process(parentTask);
        assertThat(result.mIdealRecord).isNotNull();

        // Using alias activity to find task.
        final ActivityRecord r2 = new ActivityBuilder(mAtm).setComponent(
                alias).setTargetActivity(targetActivity).build();
        result = new RootWindowContainer.FindTaskResult();
        result.process(r2, parentTask);
        assertThat(result.mRecord).isNotNull();
        result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info);
        result.process(parentTask);
        assertThat(result.mIdealRecord).isNotNull();
    }

    @Test