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

Commit 01fff9bf authored by Kazuki Takise's avatar Kazuki Takise
Browse files

Migrate TaskInfo#isFocused to FocusTransitionObserver for windecor

Confusingly, TaskInfo#isFocused represents per-display focus, not
system-wide focus, which means TaskInfo#isFocused can be true for
multiple apps in multi-monitor environments. This leads to
problems such as:
- Multiple windows are highlighted as focused window.
- Clicking the window decor doesn't bring apps to front in some
  cases.

This change fixes these issues by migrating it to
FocusTransitionObserver, which is the only proper way to get
system-wide (global) focus info in WMShell.

- *WindowDecorViewModel are the only places in windowdecor/ that
get system-wide focus changes directly from
FocusTransitionObserver. There are two channels for this:
  - FocusTransitionListener#onFocusedTaskChanged(): This is used
    for relayouting window decor when only global focus has
    changed. The existing APIs such as FreeformTaskTransitionObserver
    and FullscreenTaskListener don't notify these changes.
  - In the callbacks of FocusTransitionListener and
    FreeformTaskTransitionObserver,
    FocusTransitionObserver#hasGlobalFocus() is available.
    It's guaranteed by [1] and [2] that FocusTransitionObserver
    processes a transition earlier than FreeformTaskTransitionObserver.
    For FullscreenTaskListener, there's no way to guarantee the order
    between *TaskListener and TransitionObserver, so this may lead
    to calling relayout() twice in some cases, but at least the
    final state is always correct, and we can prevent the second
    one by returning early.
- Once *WindowDecoreViewModel receives an update on global focus,
it passes the value to *WindowDecoration via the relayout*() and
update*() functions. Unfortunately it's not allowed to add global
focus to RunningTaskInfo to prevent global focus to be accessed
without synchronization in mind, so this change ends up adding
a parameter for global focus to those functions. This should be
better than calling hasGlobalFocus() in many places to make it
explicit that only *WindowDecorViewModel receives updates and they
are propagated through relayout().

Note that this should be able to be written in a cleaner way once
the unified task repository for WMShell gets ready.

[1] If3ab6dd7a68641cdf797516c8244eaa4bbb1f7ca
[2] I68b6aaa44cf8578d3dcac3277c66e3d07738eef8

Bug: 371095009
Bug: 368200134
Bug: 369227512
Flag: com.android.window.flags.enable_display_focus_in_shell_transitions
Test: atest WMShellUnitTests
Change-Id: Ib51e1cca017bc0c426c7277f8245dcfdb8703620
parent f99159c0
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -264,7 +264,8 @@ public abstract class WMShellModule {
            Optional<DesktopTasksLimiter> desktopTasksLimiter,
            AppHandleEducationController appHandleEducationController,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler) {
            Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler,
            FocusTransitionObserver focusTransitionObserver) {
        if (DesktopModeStatus.canEnterDesktopMode(context)) {
            return new DesktopModeWindowDecorViewModel(
                    context,
@@ -291,7 +292,8 @@ public abstract class WMShellModule {
                    desktopTasksLimiter,
                    appHandleEducationController,
                    windowDecorCaptionHandleRepository,
                    desktopActivityOrientationHandler);
                    desktopActivityOrientationHandler,
                    focusTransitionObserver);
        }
        return new CaptionWindowDecorViewModel(
                context,
@@ -305,7 +307,8 @@ public abstract class WMShellModule {
                displayController,
                rootTaskDisplayAreaOrganizer,
                syncQueue,
                transitions);
                transitions,
                focusTransitionObserver);
    }

    @WMSingleton
+25 −7
Original line number Diff line number Diff line
@@ -58,9 +58,11 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.shared.FocusTransitionListener;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;

@@ -68,7 +70,7 @@ import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
 * View model for the window decoration with a caption and shadows. Works with
 * {@link CaptionWindowDecoration}.
 */
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusTransitionListener {
    private static final String TAG = "CaptionWindowDecorViewModel";

    private final ShellTaskOrganizer mTaskOrganizer;
@@ -85,6 +87,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
    private final Region mExclusionRegion = Region.obtain();
    private final InputManager mInputManager;
    private TaskOperations mTaskOperations;
    private FocusTransitionObserver mFocusTransitionObserver;

    /**
     * Whether to pilfer the next motion event to send cancellations to the windows below.
@@ -121,7 +124,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            DisplayController displayController,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            SyncTransactionQueue syncQueue,
            Transitions transitions) {
            Transitions transitions,
            FocusTransitionObserver focusTransitionObserver) {
        mContext = context;
        mMainExecutor = shellExecutor;
        mMainHandler = mainHandler;
@@ -133,6 +137,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
        mSyncQueue = syncQueue;
        mTransitions = transitions;
        mFocusTransitionObserver = focusTransitionObserver;
        if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
            mTaskOperations = new TaskOperations(null, mContext, mSyncQueue);
        }
@@ -148,6 +153,16 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to register window manager callbacks", e);
        }
        mFocusTransitionObserver.setLocalFocusTransitionListener(this, mMainExecutor);
    }

    @Override
    public void onFocusedTaskChanged(int taskId, boolean isFocusedOnDisplay,
            boolean isFocusedGlobally) {
        final WindowDecoration decor = mWindowDecorByTaskId.get(taskId);
        if (decor != null) {
            decor.relayout(decor.mTaskInfo, isFocusedGlobally);
        }
    }

    @Override
@@ -180,7 +195,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            return;
        }

        decoration.relayout(taskInfo);
        decoration.relayout(taskInfo, decoration.mHasGlobalFocus);
    }

    @Override
@@ -217,7 +232,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            createWindowDecoration(taskInfo, taskSurface, startT, finishT);
        } else {
            decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
                    false /* setTaskCropAndPosition */);
                    false /* setTaskCropAndPosition */,
                    mFocusTransitionObserver.hasGlobalFocus(taskInfo));
        }
    }

@@ -230,7 +246,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        if (decoration == null) return;

        decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
                false /* setTaskCropAndPosition */);
                false /* setTaskCropAndPosition */,
                mFocusTransitionObserver.hasGlobalFocus(taskInfo));
    }

    @Override
@@ -308,7 +325,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        windowDecoration.setDragPositioningCallback(taskPositioner);
        windowDecoration.setTaskDragResizer(taskPositioner);
        windowDecoration.relayout(taskInfo, startT, finishT,
                false /* applyStartTransactionOnDraw */, false /* setTaskCropAndPosition */);
                false /* applyStartTransactionOnDraw */, false /* setTaskCropAndPosition */,
                mFocusTransitionObserver.hasGlobalFocus(taskInfo));
    }

    private class CaptionTouchEventListener implements
@@ -359,7 +377,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            }
            if (e.getAction() == MotionEvent.ACTION_DOWN) {
                final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
                if (!taskInfo.isFocused) {
                if (!mFocusTransitionObserver.hasGlobalFocus(taskInfo)) {
                    final WindowContainerTransaction wct = new WindowContainerTransaction();
                    wct.reorder(mTaskToken, true /* onTop */, true /* includingParents */);
                    mSyncQueue.queue(wct);
+8 −6
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
    }

    @Override
    void relayout(RunningTaskInfo taskInfo) {
    void relayout(RunningTaskInfo taskInfo, boolean hasGlobalFocus) {
        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        // The crop and position of the task should only be set when a task is fluid resizing. In
        // all other cases, it is expected that the transition handler positions and crops the task
@@ -185,7 +185,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
        // synced with the buffer transaction (that draws the View). Both will be shown on screen
        // at the same, whereas applying them independently causes flickering. See b/270202228.
        relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */,
                shouldSetTaskPositionAndCrop);
                shouldSetTaskPositionAndCrop, hasGlobalFocus);
    }

    @VisibleForTesting
@@ -196,12 +196,13 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
            boolean setTaskCropAndPosition,
            boolean isStatusBarVisible,
            boolean isKeyguardVisibleAndOccluded,
            InsetsState displayInsetsState) {
            InsetsState displayInsetsState,
            boolean hasGlobalFocus) {
        relayoutParams.reset();
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
        relayoutParams.mShadowRadiusId = taskInfo.isFocused
        relayoutParams.mShadowRadiusId = hasGlobalFocus
                ? R.dimen.freeform_decor_shadow_focused_thickness
                : R.dimen.freeform_decor_shadow_unfocused_thickness;
        relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
@@ -233,7 +234,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
    @SuppressLint("MissingPermission")
    void relayout(RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean setTaskCropAndPosition) {
            boolean applyStartTransactionOnDraw, boolean setTaskCropAndPosition,
            boolean hasGlobalFocus) {
        final boolean isFreeform =
                taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FREEFORM;
        final boolean isDragResizeable = ENABLE_WINDOWING_SCALED_RESIZING.isTrue()
@@ -245,7 +247,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL

        updateRelayoutParams(mRelayoutParams, taskInfo, applyStartTransactionOnDraw,
                setTaskCropAndPosition, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded,
                mDisplayController.getInsetsState(taskInfo.displayId));
                mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus);

        relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
        // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
+32 −11
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ import com.android.wm.shell.desktopmode.DesktopWallpaperActivity;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.desktopmode.education.AppHandleEducationController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.shared.FocusTransitionListener;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -124,6 +125,7 @@ import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionRegionListener;
import com.android.wm.shell.windowdecor.extension.InsetsStateKt;
@@ -133,20 +135,21 @@ import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
import kotlin.Pair;
import kotlin.Unit;

import kotlinx.coroutines.ExperimentalCoroutinesApi;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import kotlinx.coroutines.ExperimentalCoroutinesApi;

/**
 * View model for the window decoration with a caption and shadows. Works with
 * {@link DesktopModeWindowDecoration}.
 */

public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        FocusTransitionListener {
    private static final String TAG = "DesktopModeWindowDecorViewModel";

    private final DesktopModeWindowDecoration.Factory mDesktopModeWindowDecorFactory;
@@ -216,6 +219,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                }
            };
    private final TaskPositionerFactory mTaskPositionerFactory;
    private final FocusTransitionObserver mFocusTransitionObserver;

    public DesktopModeWindowDecorViewModel(
            Context context,
@@ -242,7 +246,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            Optional<DesktopTasksLimiter> desktopTasksLimiter,
            AppHandleEducationController appHandleEducationController,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler) {
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            FocusTransitionObserver focusTransitionObserver) {
        this(
                context,
                shellExecutor,
@@ -274,7 +279,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                appHandleEducationController,
                windowDecorCaptionHandleRepository,
                activityOrientationChangeHandler,
                new TaskPositionerFactory());
                new TaskPositionerFactory(),
                focusTransitionObserver);
    }

    @VisibleForTesting
@@ -309,7 +315,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            AppHandleEducationController appHandleEducationController,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            TaskPositionerFactory taskPositionerFactory) {
            TaskPositionerFactory taskPositionerFactory,
            FocusTransitionObserver focusTransitionObserver) {
        mContext = context;
        mMainExecutor = shellExecutor;
        mMainHandler = mainHandler;
@@ -369,6 +376,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            }
        };
        mTaskPositionerFactory = taskPositionerFactory;
        mFocusTransitionObserver = focusTransitionObserver;

        shellInit.addInitCallback(this::onInit, this);
    }
@@ -402,6 +410,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                        return Unit.INSTANCE;
                    });
        }
        mFocusTransitionObserver.setLocalFocusTransitionListener(this, mMainExecutor);
    }

    @Override
    public void onFocusedTaskChanged(int taskId, boolean isFocusedOnDisplay,
            boolean isFocusedGlobally) {
        final WindowDecoration decor = mWindowDecorByTaskId.get(taskId);
        if (decor != null) {
            decor.relayout(decor.mTaskInfo, isFocusedGlobally);
        }
    }

    @Override
@@ -447,7 +465,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            removeTaskFromEventReceiver(oldTaskInfo.displayId);
            incrementEventReceiverTasks(taskInfo.displayId);
        }
        decoration.relayout(taskInfo);
        decoration.relayout(taskInfo, decoration.mHasGlobalFocus);
        mActivityOrientationChangeHandler.ifPresent(handler ->
                handler.handleActivityOrientationChange(oldTaskInfo, taskInfo));
    }
@@ -486,7 +504,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            createWindowDecoration(taskInfo, taskSurface, startT, finishT);
        } else {
            decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
                    false /* shouldSetTaskPositionAndCrop */);
                    false /* shouldSetTaskPositionAndCrop */,
                    mFocusTransitionObserver.hasGlobalFocus(taskInfo));
        }
    }

@@ -499,7 +518,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        if (decoration == null) return;

        decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
                false /* shouldSetTaskPositionAndCrop */);
                false /* shouldSetTaskPositionAndCrop */,
                mFocusTransitionObserver.hasGlobalFocus(taskInfo));
    }

    @Override
@@ -895,7 +915,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        }

        private void moveTaskToFront(RunningTaskInfo taskInfo) {
            if (!taskInfo.isFocused) {
            if (!mFocusTransitionObserver.hasGlobalFocus(taskInfo)) {
                mDesktopTasksController.moveTaskToFront(taskInfo);
            }
        }
@@ -1516,7 +1536,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        windowDecoration.setExclusionRegionListener(mExclusionRegionListener);
        windowDecoration.setDragPositioningCallback(taskPositioner);
        windowDecoration.relayout(taskInfo, startT, finishT,
                false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */);
                false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */,
                mFocusTransitionObserver.hasGlobalFocus(taskInfo));
        if (!Flags.enableHandleInputFix()) {
            incrementEventReceiverTasks(taskInfo.displayId);
        }
+27 −17
Original line number Diff line number Diff line
@@ -352,7 +352,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    }

    @Override
    void relayout(ActivityManager.RunningTaskInfo taskInfo) {
    void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus) {
        final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
        // The crop and position of the task should only be set when a task is fluid resizing. In
        // all other cases, it is expected that the transition handler positions and crops the task
@@ -365,7 +365,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        // the View). Both will be shown on screen at the same, whereas applying them independently
        // causes flickering. See b/270202228.
        final boolean applyTransactionOnDraw = taskInfo.isFreeform();
        relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskPositionAndCrop);
        relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskPositionAndCrop,
                hasGlobalFocus);
        if (!applyTransactionOnDraw) {
            t.apply();
        }
@@ -373,18 +374,19 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin

    void relayout(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop,
            boolean hasGlobalFocus) {
        Trace.beginSection("DesktopModeWindowDecoration#relayout");
        if (taskInfo.isFreeform()) {
            // The Task is in Freeform mode -> show its header in sync since it's an integral part
            // of the window itself - a delayed header might cause bad UX.
            relayoutInSync(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                    shouldSetTaskPositionAndCrop);
                    shouldSetTaskPositionAndCrop, hasGlobalFocus);
        } else {
            // The Task is outside Freeform mode -> allow the handle view to be delayed since the
            // handle is just a small addition to the window.
            relayoutWithDelayedViewHost(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                    shouldSetTaskPositionAndCrop);
                    shouldSetTaskPositionAndCrop, hasGlobalFocus);
        }
        Trace.endSection();
    }
@@ -392,11 +394,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    /** Run the whole relayout phase immediately without delay. */
    private void relayoutInSync(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop,
            boolean hasGlobalFocus) {
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                shouldSetTaskPositionAndCrop);
                shouldSetTaskPositionAndCrop, hasGlobalFocus);
        if (mResult.mRootView != null) {
            updateViewHost(mRelayoutParams, startT, mResult);
        }
@@ -418,7 +421,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
     */
    private void relayoutWithDelayedViewHost(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop,
            boolean hasGlobalFocus) {
        if (applyStartTransactionOnDraw) {
            throw new IllegalArgumentException(
                    "We cannot both sync viewhost ondraw and delay viewhost creation.");
@@ -426,7 +430,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT,
                false /* applyStartTransactionOnDraw */, shouldSetTaskPositionAndCrop);
                false /* applyStartTransactionOnDraw */, shouldSetTaskPositionAndCrop,
                hasGlobalFocus);
        if (mResult.mRootView == null) {
            // This means something blocks the window decor from showing, e.g. the task is hidden.
            // Nothing is set up in this case including the decoration surface.
@@ -440,7 +445,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    @SuppressLint("MissingPermission")
    private void updateRelayoutParamsAndSurfaces(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop,
            boolean hasGlobalFocus) {
        Trace.beginSection("DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces");

        if (Flags.enableDesktopWindowingAppToWeb()) {
@@ -459,7 +465,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                .isTaskInFullImmersiveState(taskInfo.taskId);
        updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
                shouldSetTaskPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded,
                inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId));
                inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId),
                hasGlobalFocus);

        final WindowDecorLinearLayout oldRootView = mResult.mRootView;
        final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
@@ -507,12 +514,13 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            ));
        } else {
            mWindowDecorViewHolder.bindData(new AppHeaderViewHolder.HeaderData(
                    mTaskInfo, TaskInfoKt.getRequestingImmersive(mTaskInfo), inFullImmersive
                    mTaskInfo, TaskInfoKt.getRequestingImmersive(mTaskInfo), inFullImmersive,
                    hasGlobalFocus
            ));
        }
        Trace.endSection();

        if (!mTaskInfo.isFocused) {
        if (!hasGlobalFocus) {
            closeHandleMenu();
            closeManageWindowsMenu();
            closeMaximizeMenu();
@@ -780,7 +788,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            boolean isStatusBarVisible,
            boolean isKeyguardVisibleAndOccluded,
            boolean inFullImmersiveMode,
            @NonNull InsetsState displayInsetsState) {
            @NonNull InsetsState displayInsetsState,
            boolean hasGlobalFocus) {
        final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode());
        final boolean isAppHeader =
                captionLayoutId == R.layout.desktop_mode_app_header;
@@ -790,6 +799,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        relayoutParams.mLayoutResId = captionLayoutId;
        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
        relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
        relayoutParams.mHasGlobalFocus = hasGlobalFocus;

        final boolean showCaption;
        if (Flags.enableFullyImmersiveInDesktop()) {
@@ -865,8 +875,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            relayoutParams.mInputFeatures
                    |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
        }
        if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) {
            relayoutParams.mShadowRadiusId = taskInfo.isFocused
        if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ hasGlobalFocus)) {
            relayoutParams.mShadowRadiusId = hasGlobalFocus
                    ? R.dimen.freeform_decor_shadow_focused_thickness
                    : R.dimen.freeform_decor_shadow_unfocused_thickness;
        }
@@ -1408,7 +1418,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    }

    boolean isFocused() {
        return mTaskInfo.isFocused;
        return mHasGlobalFocus;
    }

    /**
Loading