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

Commit 4c008874 authored by Jorge Gil's avatar Jorge Gil
Browse files

Add WindowDecorViewHost and WindowDecorViewHostSupplier

Creates an abstraction for creating, updating and releasing the surface
and view hierarchy drawn by the WindowDecoration (aka the caption bar).
Also provides a default implementation that supports rendering the view
hierarchy synchronously and asynchronously.

There's no behavioral effects in this change, it just moves the "async"
ability to the base WindowDecoration class from the
DesktopModeWindowDecoration, and it sets up the decorations to allow
swapping the default implementation with a new (and flagged)
WindowDecorViewHost that allows warming up the view host and a new
WindowDecorViewHostSupplier implementation that allows caching/reusing
WindowDecorViewHosts, which will be introduced in a follow up change.

Bug: 360452034
Flag: EXEMPT refactor
Test: m WMShellUnitTests
Change-Id: Iae7589879d56d802c85b8c4a72a8dcc9b20d6afb
parent 5ceda28d
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.dagger;

import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
@@ -114,6 +115,8 @@ import com.android.wm.shell.unfold.qualifier.UnfoldTransition;
import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import com.android.wm.shell.windowdecor.viewhost.DefaultWindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier;

import dagger.Binds;
import dagger.Lazy;
@@ -244,7 +247,8 @@ public abstract class WMShellModule {
            AssistContentRequester assistContentRequester,
            MultiInstanceHelper multiInstanceHelper,
            Optional<DesktopTasksLimiter> desktopTasksLimiter,
            Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler) {
            Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
        if (DesktopModeStatus.canEnterDesktopMode(context)) {
            return new DesktopModeWindowDecorViewModel(
                    context,
@@ -268,7 +272,8 @@ public abstract class WMShellModule {
                    assistContentRequester,
                    multiInstanceHelper,
                    desktopTasksLimiter,
                    desktopActivityOrientationHandler);
                    desktopActivityOrientationHandler,
                    windowDecorViewHostSupplier);
        }
        return new CaptionWindowDecorViewModel(
                context,
@@ -282,7 +287,8 @@ public abstract class WMShellModule {
                displayController,
                rootTaskDisplayAreaOrganizer,
                syncQueue,
                transitions);
                transitions,
                windowDecorViewHostSupplier);
    }

    @WMSingleton
@@ -371,6 +377,13 @@ public abstract class WMShellModule {
                context, shellInit, transitions, windowDecorViewModel);
    }

    @WMSingleton
    @Provides
    static WindowDecorViewHostSupplier provideWindowDecorViewHostSupplier(
            @ShellMainThread @NonNull CoroutineScope mainScope) {
        return new DefaultWindowDecorViewHostSupplier(mainScope);
    }

    //
    // One handed mode
    //
+7 −2
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier;

/**
 * View model for the window decoration with a caption and shadows. Works with
@@ -83,6 +84,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
    private final Transitions mTransitions;
    private final Region mExclusionRegion = Region.obtain();
    private final InputManager mInputManager;
    private final WindowDecorViewHostSupplier mWindowDecorViewHostSupplier;
    private TaskOperations mTaskOperations;

    /**
@@ -120,7 +122,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            DisplayController displayController,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            SyncTransactionQueue syncQueue,
            Transitions transitions) {
            Transitions transitions,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
        mContext = context;
        mMainExecutor = shellExecutor;
        mMainHandler = mainHandler;
@@ -132,6 +135,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
        mSyncQueue = syncQueue;
        mTransitions = transitions;
        mWindowDecorViewHostSupplier = windowDecorViewHostSupplier;
        if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
            mTaskOperations = new TaskOperations(null, mContext, mSyncQueue);
        }
@@ -295,7 +299,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
                        mMainHandler,
                        mBgExecutor,
                        mMainChoreographer,
                        mSyncQueue);
                        mSyncQueue,
                        mWindowDecorViewHostSupplier);
        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);

        final FluidResizeTaskPositioner taskPositioner =
+5 −2
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier;

/**
 * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
@@ -88,8 +89,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
            Handler handler,
            @ShellBackgroundThread ShellExecutor bgExecutor,
            Choreographer choreographer,
            SyncTransactionQueue syncQueue) {
        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface);
            SyncTransactionQueue syncQueue,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
                windowDecorViewHostSupplier);
        mHandler = handler;
        mBgExecutor = bgExecutor;
        mChoreographer = choreographer;
+9 −3
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionReg
import com.android.wm.shell.windowdecor.extension.InsetsStateKt;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier;

import kotlin.Unit;

@@ -155,6 +156,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
    private final InteractionJankMonitor mInteractionJankMonitor;
    private final MultiInstanceHelper mMultiInstanceHelper;
    private final Optional<DesktopTasksLimiter> mDesktopTasksLimiter;
    private final WindowDecorViewHostSupplier mWindowDecorViewHostSupplier;
    private boolean mTransitionDragActive;

    private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
@@ -223,8 +225,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            AssistContentRequester assistContentRequester,
            MultiInstanceHelper multiInstanceHelper,
            Optional<DesktopTasksLimiter> desktopTasksLimiter,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler
    ) {
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
        this(
                context,
                shellExecutor,
@@ -244,6 +246,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                genericLinksParser,
                assistContentRequester,
                multiInstanceHelper,
                windowDecorViewHostSupplier,
                new DesktopModeWindowDecoration.Factory(),
                new InputMonitorFactory(),
                SurfaceControl.Transaction::new,
@@ -275,6 +278,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            AppToWebGenericLinksParser genericLinksParser,
            AssistContentRequester assistContentRequester,
            MultiInstanceHelper multiInstanceHelper,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier,
            DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
            InputMonitorFactory inputMonitorFactory,
            Supplier<SurfaceControl.Transaction> transactionFactory,
@@ -300,6 +304,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        mMultiInstanceHelper = multiInstanceHelper;
        mShellCommandHandler = shellCommandHandler;
        mWindowManager = windowManager;
        mWindowDecorViewHostSupplier = windowDecorViewHostSupplier;
        mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory;
        mInputMonitorFactory = inputMonitorFactory;
        mTransactionFactory = transactionFactory;
@@ -1284,7 +1289,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                        mRootTaskDisplayAreaOrganizer,
                        mGenericLinksParser,
                        mAssistContentRequester,
                        mMultiInstanceHelper);
                        mMultiInstanceHelper,
                        mWindowDecorViewHostSupplier);
        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);

        final TaskPositioner taskPositioner = mTaskPositionerFactory.create(
+20 −82
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResiz

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration.WindowingMode;
import android.app.assist.AssistContent;
@@ -92,6 +91,7 @@ import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewholder.AppHandleViewHolder;
import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
import com.android.wm.shell.windowdecor.viewholder.WindowDecorationViewHolder;
import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier;

import kotlin.Unit;
import kotlin.jvm.functions.Function0;
@@ -134,12 +134,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private DragPositioningCallback mDragPositioningCallback;
    private DragResizeInputListener mDragResizeListener;
    private DragDetector mDragDetector;
    private Runnable mCurrentViewHostRunnable = null;
    private RelayoutParams mRelayoutParams = new RelayoutParams();
    private final WindowDecoration.RelayoutResult<WindowDecorLinearLayout> mResult =
            new WindowDecoration.RelayoutResult<>();
    private final Runnable mViewHostRunnable =
            () -> updateViewHost(mRelayoutParams, null /* onDrawTransaction */, mResult);

    private final Point mPositionInParent = new Point();
    private HandleMenu mHandleMenu;
@@ -190,14 +187,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            AppToWebGenericLinksParser genericLinksParser,
            AssistContentRequester assistContentRequester,
            MultiInstanceHelper multiInstanceHelper) {
            MultiInstanceHelper multiInstanceHelper,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
        this (context, userContext, displayController, splitScreenController, taskOrganizer,
                taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
                rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester,
                SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
                WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(
                        context.getSystemService(WindowManager.class)),
                new SurfaceControlViewHostFactory() {}, DefaultMaximizeMenuFactory.INSTANCE,
                new SurfaceControlViewHostFactory() {}, windowDecorViewHostSupplier,
                DefaultMaximizeMenuFactory.INSTANCE,
                DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper);
    }

@@ -222,13 +221,14 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            Supplier<SurfaceControl> surfaceControlSupplier,
            WindowManagerWrapper windowManagerWrapper,
            SurfaceControlViewHostFactory surfaceControlViewHostFactory,
            WindowDecorViewHostSupplier windowDecorViewHostSupplier,
            MaximizeMenuFactory maximizeMenuFactory,
            HandleMenuFactory handleMenuFactory,
            MultiInstanceHelper multiInstanceHelper) {
        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
                surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
                windowContainerTransactionSupplier, surfaceControlSupplier,
                surfaceControlViewHostFactory);
                surfaceControlViewHostFactory, windowDecorViewHostSupplier);
        mSplitScreenController = splitScreenController;
        mHandler = handler;
        mBgExecutor = bgExecutor;
@@ -337,73 +337,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
        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);
        } 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);
        }
        Trace.endSection();
    }

    /** Run the whole relayout phase immediately without delay. */
    private void relayoutInSync(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                shouldSetTaskPositionAndCrop);
        if (mResult.mRootView != null) {
            updateViewHost(mRelayoutParams, startT, mResult);
        }
    }

    /**
     * Clear the current ViewHost runnable - to ensure it doesn't run once relayout params have been
     * updated.
     */
    private void clearCurrentViewHostRunnable() {
        if (mCurrentViewHostRunnable != null) {
            mHandler.removeCallbacks(mCurrentViewHostRunnable);
            mCurrentViewHostRunnable = null;
        }
    }

    /**
     * Relayout the window decoration but repost some of the work, to unblock the current callstack.
     */
    private void relayoutWithDelayedViewHost(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
        if (applyStartTransactionOnDraw) {
            throw new IllegalArgumentException(
                    "We cannot both sync viewhost ondraw and delay viewhost creation.");
        }
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT,
                false /* applyStartTransactionOnDraw */, shouldSetTaskPositionAndCrop);
        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.
            return;
        }
        // Store the current runnable so it can be removed if we start a new relayout.
        mCurrentViewHostRunnable = mViewHostRunnable;
        mHandler.post(mCurrentViewHostRunnable);
    }

    @SuppressLint("MissingPermission")
    private void updateRelayoutParamsAndSurfaces(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
        Trace.beginSection("DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces");

        if (Flags.enableDesktopWindowingAppToWeb()) {
            setCapturedLink(taskInfo.capturedLink, taskInfo.capturedLinkTimestamp);
@@ -420,8 +353,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
        final WindowContainerTransaction wct = new WindowContainerTransaction();

        Trace.beginSection("DesktopModeWindowDecoration#relayout-updateViewsAndSurfaces");
        updateViewsAndSurfaces(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
        Trace.beginSection("DesktopModeWindowDecoration#relayout-inner");
        relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
        Trace.endSection();
        // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo

@@ -433,7 +366,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            // 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.
            disposeStatusBarInputLayer();
            Trace.endSection(); // DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces
            Trace.endSection(); // DesktopModeWindowDecoration#relayout
            return;
        }

@@ -441,12 +374,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            disposeStatusBarInputLayer();
            mWindowDecorViewHolder = createViewHolder();
        }
        Trace.beginSection("DesktopModeWindowDecoration#relayout-binding");

        final Point position = new Point();
        if (isAppHandle(mWindowDecorViewHolder)) {
            position.set(determineHandlePosition());
        }
        Trace.beginSection("DesktopModeWindowDecoration#relayout-bindData");
        mWindowDecorViewHolder.bindData(mTaskInfo,
                position,
                mResult.mCaptionWidth,
@@ -460,7 +393,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        }
        updateDragResizeListener(oldDecorationSurface);
        updateMaximizeMenu(startT);
        Trace.endSection(); // DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces
        Trace.endSection(); // DesktopModeWindowDecoration#relayout
    }

    private boolean isCaptionVisible() {
@@ -638,6 +571,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        relayoutParams.mLayoutResId = captionLayoutId;
        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
        relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
        // Allow the handle view to be delayed since the handle is just a small addition to the
        // window, whereas the header cannot be delayed because it is expected to be visible from
        // the first frame.
        relayoutParams.mAsyncViewHost = isAppHandle;

        if (isAppHeader) {
            if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
@@ -1253,7 +1190,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        mExclusionRegionListener.onExclusionRegionDismissed(mTaskInfo.taskId);
        disposeResizeVeil();
        disposeStatusBarInputLayer();
        clearCurrentViewHostRunnable();
        super.close();
    }

@@ -1364,7 +1300,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
                AppToWebGenericLinksParser genericLinksParser,
                AssistContentRequester assistContentRequester,
                MultiInstanceHelper multiInstanceHelper) {
                MultiInstanceHelper multiInstanceHelper,
                WindowDecorViewHostSupplier windowDecorViewHostSupplier) {
            return new DesktopModeWindowDecoration(
                    context,
                    userContext,
@@ -1380,7 +1317,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                    rootTaskDisplayAreaOrganizer,
                    genericLinksParser,
                    assistContentRequester,
                    multiInstanceHelper);
                    multiInstanceHelper,
                    windowDecorViewHostSupplier);
        }
    }

Loading