Loading services/core/java/com/android/server/wm/ActivityStarter.java +2 −1 Original line number Diff line number Diff line Loading @@ -2784,7 +2784,8 @@ class ActivityStarter { } } else { // Use the child TaskFragment (if any) as the new parent if the activity can be embedded final ActivityRecord top = task.topRunningActivity(); final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */, false /* includingEmbeddedTask */); newParent = top != null ? top.getTaskFragment() : task; } Loading services/core/java/com/android/server/wm/RootWindowContainer.java +19 −1 Original line number Diff line number Diff line Loading @@ -365,8 +365,26 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return false; } if (matchingCandidate(task)) { return true; } // Looking for the embedded tasks (if any) return !task.isLeafTaskFragment() && task.forAllLeafTaskFragments( this::matchingCandidate); } boolean matchingCandidate(TaskFragment taskFragment) { final Task task = taskFragment.asTask(); if (task == null) { return false; } // Overlays should not be considered as the task's logical top activity. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */); // Activities of the tasks that embedded from this one should not be used. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */, false /* includingEmbeddedTask */); if (r == null || r.finishing || r.mUserId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r); Loading services/core/java/com/android/server/wm/Task.java +44 −10 Original line number Diff line number Diff line Loading @@ -1394,14 +1394,6 @@ class Task extends TaskFragment { return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone); } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); } ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { return getTopActivity(false /*includeFinishing*/, includeOverlays); } ActivityRecord topRunningActivityLocked() { if (getParent() == null) { return null; Loading Loading @@ -2976,11 +2968,53 @@ class Task extends TaskFragment { /** Returns the top-most activity that occludes the given one, or {@code null} if none. */ @Nullable ActivityRecord getOccludingActivityAbove(ActivityRecord activity) { final ActivityRecord top = getActivity(ActivityRecord::occludesParent, true /* traverseTopToBottom */, activity); final ActivityRecord top = getActivity(r -> { if (!r.occludesParent()) { return false; } if (r == activity) { // Reached the given activity, return the activity to stop searching. return true; } TaskFragment parent = r.getTaskFragment(); if (parent == activity.getTaskFragment()) { // Found it. This activity on top of the given activity on the same TaskFragment. return true; } if (isSelfOrNonEmbeddedTask(parent.asTask())) { // Found it. This activity is the direct child of a leaf Task without being // embedded. return true; } // The candidate activity is being embedded. Checking if the bounds of the containing // TaskFragment equals to the outer TaskFragment. TaskFragment grandParent = parent.getParent().asTaskFragment(); while (grandParent != null) { if (!parent.getBounds().equals(grandParent.getBounds())) { // Not occluding the grandparent. break; } if (isSelfOrNonEmbeddedTask(grandParent.asTask())) { // Found it. The activity occludes its parent TaskFragment and the parent // TaskFragment also occludes its parent all the way up. return true; } parent = grandParent; grandParent = parent.getParent().asTaskFragment(); } return false; }); return top != activity ? top : null; } private boolean isSelfOrNonEmbeddedTask(Task task) { if (task == this) { return true; } return task != null && !task.isEmbedded(); } @Override public SurfaceControl.Builder makeAnimationLeash() { return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId); Loading services/core/java/com/android/server/wm/TaskFragment.java +54 −3 Original line number Diff line number Diff line Loading @@ -614,17 +614,68 @@ class TaskFragment extends WindowContainer<WindowContainer> { return false; } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); } ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { return getTopNonFinishingActivity(includeOverlays, true /* includingEmbeddedTask */); } /** * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to * the current user. * @param includeOverlays whether the task overlay activity should be included. * @param includingEmbeddedTask whether the activity in a task that being embedded from this * one should be included. * @see #topRunningActivity(boolean, boolean) * @see ActivityRecord#okToShowLocked() */ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays, boolean includingEmbeddedTask) { // Split into 4 to avoid object creation due to variable capture. if (includeOverlays) { if (includingEmbeddedTask) { return getActivity((r) -> !r.finishing); } return getActivity((r) -> !r.finishing && r.getTask() == this.getTask()); } if (includingEmbeddedTask) { return getActivity((r) -> !r.finishing && !r.isTaskOverlay()); } return getActivity( (r) -> !r.finishing && !r.isTaskOverlay() && r.getTask() == this.getTask()); } ActivityRecord topRunningActivity() { return topRunningActivity(false /* focusableOnly */); } ActivityRecord topRunningActivity(boolean focusableOnly) { // Split into 2 to avoid object creation due to variable capture. return topRunningActivity(focusableOnly, true /* includingEmbeddedTask */); } /** * Returns the top-most running activity, which the activity is non-finishing and ok to show * to the current user. * * @see ActivityRecord#canBeTopRunning() */ ActivityRecord topRunningActivity(boolean focusableOnly, boolean includingEmbeddedTask) { // Split into 4 to avoid object creation due to variable capture. if (focusableOnly) { if (includingEmbeddedTask) { return getActivity((r) -> r.canBeTopRunning() && r.isFocusable()); } else { } return getActivity( (r) -> r.canBeTopRunning() && r.isFocusable() && r.getTask() == this.getTask()); } if (includingEmbeddedTask) { return getActivity(ActivityRecord::canBeTopRunning); } return getActivity((r) -> r.canBeTopRunning() && r.getTask() == this.getTask()); } boolean isTopActivityFocusable() { Loading Loading
services/core/java/com/android/server/wm/ActivityStarter.java +2 −1 Original line number Diff line number Diff line Loading @@ -2784,7 +2784,8 @@ class ActivityStarter { } } else { // Use the child TaskFragment (if any) as the new parent if the activity can be embedded final ActivityRecord top = task.topRunningActivity(); final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */, false /* includingEmbeddedTask */); newParent = top != null ? top.getTaskFragment() : task; } Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +19 −1 Original line number Diff line number Diff line Loading @@ -365,8 +365,26 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return false; } if (matchingCandidate(task)) { return true; } // Looking for the embedded tasks (if any) return !task.isLeafTaskFragment() && task.forAllLeafTaskFragments( this::matchingCandidate); } boolean matchingCandidate(TaskFragment taskFragment) { final Task task = taskFragment.asTask(); if (task == null) { return false; } // Overlays should not be considered as the task's logical top activity. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */); // Activities of the tasks that embedded from this one should not be used. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */, false /* includingEmbeddedTask */); if (r == null || r.finishing || r.mUserId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r); Loading
services/core/java/com/android/server/wm/Task.java +44 −10 Original line number Diff line number Diff line Loading @@ -1394,14 +1394,6 @@ class Task extends TaskFragment { return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone); } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); } ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { return getTopActivity(false /*includeFinishing*/, includeOverlays); } ActivityRecord topRunningActivityLocked() { if (getParent() == null) { return null; Loading Loading @@ -2976,11 +2968,53 @@ class Task extends TaskFragment { /** Returns the top-most activity that occludes the given one, or {@code null} if none. */ @Nullable ActivityRecord getOccludingActivityAbove(ActivityRecord activity) { final ActivityRecord top = getActivity(ActivityRecord::occludesParent, true /* traverseTopToBottom */, activity); final ActivityRecord top = getActivity(r -> { if (!r.occludesParent()) { return false; } if (r == activity) { // Reached the given activity, return the activity to stop searching. return true; } TaskFragment parent = r.getTaskFragment(); if (parent == activity.getTaskFragment()) { // Found it. This activity on top of the given activity on the same TaskFragment. return true; } if (isSelfOrNonEmbeddedTask(parent.asTask())) { // Found it. This activity is the direct child of a leaf Task without being // embedded. return true; } // The candidate activity is being embedded. Checking if the bounds of the containing // TaskFragment equals to the outer TaskFragment. TaskFragment grandParent = parent.getParent().asTaskFragment(); while (grandParent != null) { if (!parent.getBounds().equals(grandParent.getBounds())) { // Not occluding the grandparent. break; } if (isSelfOrNonEmbeddedTask(grandParent.asTask())) { // Found it. The activity occludes its parent TaskFragment and the parent // TaskFragment also occludes its parent all the way up. return true; } parent = grandParent; grandParent = parent.getParent().asTaskFragment(); } return false; }); return top != activity ? top : null; } private boolean isSelfOrNonEmbeddedTask(Task task) { if (task == this) { return true; } return task != null && !task.isEmbedded(); } @Override public SurfaceControl.Builder makeAnimationLeash() { return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId); Loading
services/core/java/com/android/server/wm/TaskFragment.java +54 −3 Original line number Diff line number Diff line Loading @@ -614,17 +614,68 @@ class TaskFragment extends WindowContainer<WindowContainer> { return false; } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); } ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { return getTopNonFinishingActivity(includeOverlays, true /* includingEmbeddedTask */); } /** * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to * the current user. * @param includeOverlays whether the task overlay activity should be included. * @param includingEmbeddedTask whether the activity in a task that being embedded from this * one should be included. * @see #topRunningActivity(boolean, boolean) * @see ActivityRecord#okToShowLocked() */ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays, boolean includingEmbeddedTask) { // Split into 4 to avoid object creation due to variable capture. if (includeOverlays) { if (includingEmbeddedTask) { return getActivity((r) -> !r.finishing); } return getActivity((r) -> !r.finishing && r.getTask() == this.getTask()); } if (includingEmbeddedTask) { return getActivity((r) -> !r.finishing && !r.isTaskOverlay()); } return getActivity( (r) -> !r.finishing && !r.isTaskOverlay() && r.getTask() == this.getTask()); } ActivityRecord topRunningActivity() { return topRunningActivity(false /* focusableOnly */); } ActivityRecord topRunningActivity(boolean focusableOnly) { // Split into 2 to avoid object creation due to variable capture. return topRunningActivity(focusableOnly, true /* includingEmbeddedTask */); } /** * Returns the top-most running activity, which the activity is non-finishing and ok to show * to the current user. * * @see ActivityRecord#canBeTopRunning() */ ActivityRecord topRunningActivity(boolean focusableOnly, boolean includingEmbeddedTask) { // Split into 4 to avoid object creation due to variable capture. if (focusableOnly) { if (includingEmbeddedTask) { return getActivity((r) -> r.canBeTopRunning() && r.isFocusable()); } else { } return getActivity( (r) -> r.canBeTopRunning() && r.isFocusable() && r.getTask() == this.getTask()); } if (includingEmbeddedTask) { return getActivity(ActivityRecord::canBeTopRunning); } return getActivity((r) -> r.canBeTopRunning() && r.getTask() == this.getTask()); } boolean isTopActivityFocusable() { Loading