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

Commit 84976417 authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge "Check for display cutout for status bar height" into main

parents 3afd3041 10ecfcb5
Loading
Loading
Loading
Loading
+9 −5
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ import android.graphics.drawable.GradientDrawable;
import android.os.Handler;
import android.os.Handler;
import android.util.Size;
import android.util.Size;
import android.view.Choreographer;
import android.view.Choreographer;
import android.view.Display;
import android.view.InsetsState;
import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
@@ -67,6 +68,8 @@ import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;


import java.util.function.BiFunction;

/**
/**
 * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
 * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
 * {@link CaptionWindowDecorViewModel}. The caption bar contains a back button, minimize button,
 * {@link CaptionWindowDecorViewModel}. The caption bar contains a back button, minimize button,
@@ -218,7 +221,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
        relayoutParams.reset();
        relayoutParams.reset();
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
        relayoutParams.mCaptionHeightCalculator = getCaptionHeightCalculator();
        if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
        if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
            relayoutParams.mShadowRadiusId = hasGlobalFocus
            relayoutParams.mShadowRadiusId = hasGlobalFocus
                    ? R.dimen.freeform_decor_shadow_focused_thickness
                    ? R.dimen.freeform_decor_shadow_focused_thickness
@@ -445,12 +448,13 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
    }
    }


    @Override
    @Override
    int getCaptionHeightId(@WindowingMode int windowingMode) {
    int getCaptionHeight(@WindowingMode int windowingMode) {
        return getCaptionHeightIdStatic(windowingMode);
        return getCaptionHeightCalculator().apply(mContext, mDisplay);
    }
    }


    private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) {
    private static BiFunction<Context, Display, Integer> getCaptionHeightCalculator() {
        return R.dimen.freeform_decor_caption_height;
        return (ctx, display) -> loadDimensionPixelSize(ctx.getResources(),
                R.dimen.freeform_decor_caption_height);
    }
    }


    @Override
    @Override
+2 −1
Original line number Original line Diff line number Diff line
@@ -135,7 +135,8 @@ public class CarWindowDecoration extends WindowDecoration<WindowDecorLinearLayou
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mRunningTaskInfo = taskInfo;
        // todo(b/382071404): update to car specific UI
        // todo(b/382071404): update to car specific UI
        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
        relayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
        relayoutParams.mCaptionHeightCalculator = (ctx, display) ->
                loadDimensionPixelSize(ctx.getResources(), R.dimen.freeform_decor_caption_height);
        relayoutParams.mIsCaptionVisible =
        relayoutParams.mIsCaptionVisible =
                isCaptionVisible && mIsStatusBarVisible && !mIsKeyguardVisibleAndOccluded;
                isCaptionVisible && mIsStatusBarVisible && !mIsKeyguardVisibleAndOccluded;
        relayoutParams.mCaptionTopPadding = getTopPadding(taskInfo, relayoutParams);
        relayoutParams.mCaptionTopPadding = getTopPadding(taskInfo, relayoutParams);
+18 −12
Original line number Original line Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.Size;
import android.util.Size;
import android.view.Choreographer;
import android.view.Choreographer;
import android.view.Display;
import android.view.InsetsState;
import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
@@ -78,6 +79,7 @@ import android.window.TaskSnapshot;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.window.flags.Flags;
import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.R;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -122,6 +124,7 @@ import kotlinx.coroutines.MainCoroutineDispatcher;


import java.util.List;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.Supplier;


@@ -973,7 +976,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        relayoutParams.reset();
        relayoutParams.reset();
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mRunningTaskInfo = taskInfo;
        relayoutParams.mLayoutResId = captionLayoutId;
        relayoutParams.mLayoutResId = captionLayoutId;
        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
        relayoutParams.mCaptionHeightCalculator = getCaptionHeightCalculator(
                taskInfo.getWindowingMode());
        relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
        relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
        relayoutParams.mHasGlobalFocus = hasGlobalFocus;
        relayoutParams.mHasGlobalFocus = hasGlobalFocus;
        relayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
        relayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
@@ -1850,19 +1854,21 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        return mResult.mCaptionX;
        return mResult.mCaptionX;
    }
    }


    @Override
    private static BiFunction<Context, Display, Integer> getCaptionHeightCalculator(
    int getCaptionHeightId(@WindowingMode int windowingMode) {
            @WindowingMode int windowingMode) {
        return getCaptionHeightIdStatic(windowingMode);
        return (ctx, display) -> {
            if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
                return SystemBarUtils.getStatusBarHeight(ctx.getResources(), display.getCutout());
            } else {
                return loadDimensionPixelSize(ctx.getResources(),
                        getDesktopViewAppHeaderHeightId());
            }
            }

        };
    private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) {
        return windowingMode == WINDOWING_MODE_FULLSCREEN
                ? com.android.internal.R.dimen.status_bar_height_default
                : getDesktopViewAppHeaderHeightId();
    }
    }


    private int getCaptionHeight(@WindowingMode int windowingMode) {
    @Override
        return loadDimensionPixelSize(mContext.getResources(), getCaptionHeightId(windowingMode));
    int getCaptionHeight(@WindowingMode int windowingMode) {
        return getCaptionHeightCalculator(windowingMode).apply(mContext, mDisplay);
    }
    }


    @Override
    @Override
+9 −9
Original line number Original line Diff line number Diff line
@@ -68,6 +68,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.function.Supplier;


/**
/**
@@ -281,8 +282,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        outResult.mHeight = taskBounds.height();
        outResult.mHeight = taskBounds.height();
        outResult.mRootView.setTaskFocusState(mHasGlobalFocus);
        outResult.mRootView.setTaskFocusState(mHasGlobalFocus);
        final Resources resources = mDecorWindowContext.getResources();
        final Resources resources = mDecorWindowContext.getResources();
        outResult.mCaptionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId)
        outResult.mCaptionHeight = params.mCaptionHeightCalculator.apply(mDecorWindowContext,
                + params.mCaptionTopPadding;
                mDisplay) + params.mCaptionTopPadding;
        outResult.mCaptionWidth = params.mCaptionWidthId != Resources.ID_NULL
        outResult.mCaptionWidth = params.mCaptionWidthId != Resources.ID_NULL
                ? loadDimensionPixelSize(resources, params.mCaptionWidthId) : taskBounds.width();
                ? loadDimensionPixelSize(resources, params.mCaptionWidthId) : taskBounds.width();
        outResult.mCaptionX = (outResult.mWidth - outResult.mCaptionWidth) / 2;
        outResult.mCaptionX = (outResult.mWidth - outResult.mCaptionWidth) / 2;
@@ -673,8 +674,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        captionView.setVisibility(v);
        captionView.setVisibility(v);
    }
    }


    int getCaptionHeightId(@WindowingMode int windowingMode) {
    int getCaptionHeight(@WindowingMode int windowingMode) {
        return Resources.ID_NULL;
        return 0;
    }
    }


    int getCaptionViewId() {
    int getCaptionViewId() {
@@ -822,12 +823,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
     * Adds caption inset source to a WCT
     * Adds caption inset source to a WCT
     */
     */
    public void addCaptionInset(WindowContainerTransaction wct) {
    public void addCaptionInset(WindowContainerTransaction wct) {
        final int captionHeightId = getCaptionHeightId(mTaskInfo.getWindowingMode());
        final int captionHeight = getCaptionHeight(mTaskInfo.getWindowingMode());
        if (captionHeightId == Resources.ID_NULL || !mIsCaptionVisible) {
        if (captionHeight == 0 || !mIsCaptionVisible) {
            return;
            return;
        }
        }


        final int captionHeight = loadDimensionPixelSize(mContext.getResources(), captionHeightId);
        final Rect captionInsets = new Rect(0, 0, 0, captionHeight);
        final Rect captionInsets = new Rect(0, 0, 0, captionHeight);
        final WindowDecorationInsets newInsets = new WindowDecorationInsets(mTaskInfo.token,
        final WindowDecorationInsets newInsets = new WindowDecorationInsets(mTaskInfo.token,
                mOwner, captionInsets, null  /* taskFrame */,  null /* boundingRects */,
                mOwner, captionInsets, null  /* taskFrame */,  null /* boundingRects */,
@@ -841,7 +841,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
    static class RelayoutParams {
    static class RelayoutParams {
        RunningTaskInfo mRunningTaskInfo;
        RunningTaskInfo mRunningTaskInfo;
        int mLayoutResId;
        int mLayoutResId;
        int mCaptionHeightId;
        BiFunction<Context, Display, Integer> mCaptionHeightCalculator = (ctx, display) -> 0;
        int mCaptionWidthId;
        int mCaptionWidthId;
        final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
        final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
        boolean mLimitTouchRegionToSystemAreas;
        boolean mLimitTouchRegionToSystemAreas;
@@ -872,7 +872,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>


        void reset() {
        void reset() {
            mLayoutResId = Resources.ID_NULL;
            mLayoutResId = Resources.ID_NULL;
            mCaptionHeightId = Resources.ID_NULL;
            mCaptionHeightCalculator = (ctx, display) -> 0;
            mCaptionWidthId = Resources.ID_NULL;
            mCaptionWidthId = Resources.ID_NULL;
            mOccludingCaptionElements.clear();
            mOccludingCaptionElements.clear();
            mLimitTouchRegionToSystemAreas = false;
            mLimitTouchRegionToSystemAreas = false;
+62 −3
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region;
@@ -75,6 +76,7 @@ import android.testing.TestableLooper;
import android.view.AttachedSurfaceControl;
import android.view.AttachedSurfaceControl;
import android.view.Choreographer;
import android.view.Choreographer;
import android.view.Display;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.GestureDetector;
import android.view.GestureDetector;
import android.view.InsetsSource;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.InsetsState;
@@ -101,6 +103,7 @@ import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -179,6 +182,10 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
    @Mock
    @Mock
    private DisplayController mMockDisplayController;
    private DisplayController mMockDisplayController;
    @Mock
    @Mock
    private Display mDefaultDisplay;
    @Mock
    private DisplayLayout mDisplayLayout;
    @Mock
    private SplitScreenController mMockSplitScreenController;
    private SplitScreenController mMockSplitScreenController;
    @Mock
    @Mock
    private ShellTaskOrganizer mMockShellTaskOrganizer;
    private ShellTaskOrganizer mMockShellTaskOrganizer;
@@ -299,9 +306,10 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
        final ResolveInfo resolveInfo = createResolveInfo(false /* handleAllWebDataUri */);
        final ResolveInfo resolveInfo = createResolveInfo(false /* handleAllWebDataUri */);
        when(mMockPackageManager.resolveActivityAsUser(any(), anyInt(), anyInt()))
        when(mMockPackageManager.resolveActivityAsUser(any(), anyInt(), anyInt()))
                .thenReturn(resolveInfo);
                .thenReturn(resolveInfo);
        final Display defaultDisplay = mock(Display.class);
        doReturn(mDefaultDisplay).when(mMockDisplayController).getDisplay(Display.DEFAULT_DISPLAY);
        doReturn(defaultDisplay).when(mMockDisplayController).getDisplay(Display.DEFAULT_DISPLAY);
        doReturn(mInsetsState).when(mMockDisplayController).getInsetsState(anyInt());
        doReturn(mInsetsState).when(mMockDisplayController).getInsetsState(anyInt());
        doReturn(mDisplayLayout).when(mMockDisplayController).getDisplayLayout(
                Display.DEFAULT_DISPLAY);
        when(mMockHandleMenuFactory.create(any(), any(), any(), any(), any(), anyInt(), any(),
        when(mMockHandleMenuFactory.create(any(), any(), any(), any(), any(), anyInt(), any(),
                anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(),
                anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(),
                anyBoolean(), any(), any(), anyInt(), anyInt(), anyInt(), anyInt()))
                anyBoolean(), any(), any(), anyInt(), anyInt(), anyInt(), anyInt()))
@@ -316,7 +324,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
                .thenReturn(mMockAppHandleViewHolder);
                .thenReturn(mMockAppHandleViewHolder);
        when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
        when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
        when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
        when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
        when(mMockWindowDecorViewHostSupplier.acquire(any(), eq(defaultDisplay)))
        when(mMockWindowDecorViewHostSupplier.acquire(any(), eq(mDefaultDisplay)))
                .thenReturn(mMockWindowDecorViewHost);
                .thenReturn(mMockWindowDecorViewHost);
        when(mMockWindowDecorViewHost.getSurfaceControl()).thenReturn(mock(SurfaceControl.class));
        when(mMockWindowDecorViewHost.getSurfaceControl()).thenReturn(mock(SurfaceControl.class));
    }
    }
@@ -1121,6 +1129,46 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
        assertThat(relayoutParams.mAsyncViewHost).isFalse();
        assertThat(relayoutParams.mAsyncViewHost).isFalse();
    }
    }


    @Test
    public void updateRelayoutParams_handle_hasDisplayCutout_useCutoutInCaptionHeight() {
        // Have cutout be larger than status bar so we use cutout as the caption height
        int statusBarHeight = mContext.getResources().getDimensionPixelSize(
                R.dimen.status_bar_height_default);
        int cutoutSize = statusBarHeight + 100;
        DisplayCutout cutout = createDisplayCutout(cutoutSize);
        when(mDefaultDisplay.getCutout()).thenReturn(cutout);

        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        createWindowDecoration(taskInfo, /* relayout= */ true);

        ArgumentCaptor<WindowManager.LayoutParams> captor = ArgumentCaptor.forClass(
                WindowManager.LayoutParams.class);
        verify(mMockWindowDecorViewHost).updateViewAsync(any(), captor.capture(), any(), any());
        WindowManager.LayoutParams lp = captor.getValue();
        assertThat(lp.height).isEqualTo(cutoutSize);
    }

    @Test
    public void updateRelayoutParams_header_hasDisplayCutout_ignoreCutoutInCaptionHeight() {
        // Have cutout be larger than desktop header so it would affect the size if used
        int desktopHeaderHeight = mContext.getResources().getDimensionPixelSize(
                R.dimen.desktop_view_default_header_height);
        int cutoutHeight = desktopHeaderHeight + 100;
        DisplayCutout cutout = createDisplayCutout(cutoutHeight);
        when(mDefaultDisplay.getCutout()).thenReturn(cutout);

        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
        createWindowDecoration(taskInfo, /* relayout= */ true);

        ArgumentCaptor<WindowManager.LayoutParams> captor = ArgumentCaptor.forClass(
                WindowManager.LayoutParams.class);
        verify(mMockWindowDecorViewHost).updateView(any(), captor.capture(), any(), any(), any());
        WindowManager.LayoutParams lp = captor.getValue();
        assertThat(lp.height).isEqualTo(desktopHeaderHeight);
    }

    @Test
    @Test
    public void relayout_fullscreenTask_appliesTransactionImmediately() {
    public void relayout_fullscreenTask_appliesTransactionImmediately() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
@@ -1884,6 +1932,17 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
        return createInsetsState(List.of(source));
        return createInsetsState(List.of(source));
    }
    }


    private static DisplayCutout createDisplayCutout(int cutoutSize) {
        Insets safeInsets = Insets.of(0, cutoutSize, 0, 0);
        DisplayCutout cutout = new DisplayCutout(
                safeInsets,
                /* boundLeft= */ null,
                /* boundTop= */ new Rect(0, 0, cutoutSize, cutoutSize),
                /* boundRight= */ null,
                /* boundBottom= */ null);
        return cutout;
    }

    private static class TestTouchEventListener extends GestureDetector.SimpleOnGestureListener
    private static class TestTouchEventListener extends GestureDetector.SimpleOnGestureListener
            implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener,
            implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener,
            View.OnGenericMotionListener, DragDetector.MotionEventHandler {
            View.OnGenericMotionListener, DragDetector.MotionEventHandler {
Loading