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

Commit 1c717014 authored by Tiger's avatar Tiger
Browse files

Don't let display cutout safe area be affected by status bar

Otherwise, we will get a big gap at the top edge of display while
playing landscape games on a device with waterfall cutout.

The original logic was to avoid that fullscreen apps will cut halfway
into the status bar. However, for non-waterfall cases, it can be avoided
by setting the height of display cutout the same as the height of status
bar. For the waterfall cases, althrough apps cut halfway into the status
bar, but they don't cut into the icons of status bar. This should be
fine.

This CL also removes ITYPEs from WindowLayout and WindowLayoutTests, and
moves WindowLayoutTests to coretests.

Fix: 264640845
Bug: 234093736
Test: atest WindowLayoutTests
Change-Id: Iaec9bf50b45f8f6e27695a4267cf323ae640c680
parent c0f54227
Loading
Loading
Loading
Loading
+8 −17
Original line number Diff line number Diff line
@@ -17,9 +17,9 @@
package android.view;

import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -109,14 +109,6 @@ public class WindowLayout {
            // Ensure that windows with a non-ALWAYS display cutout mode are laid out in
            // the cutout safe zone.
            final Rect displayFrame = state.getDisplayFrame();
            final InsetsSource statusBarSource = state.peekSource(ITYPE_STATUS_BAR);
            if (statusBarSource != null && displayCutoutSafe.top > displayFrame.top) {
                // Make sure that the zone we're avoiding for the cutout is at least as tall as the
                // status bar; otherwise fullscreen apps will end up cutting halfway into the status
                // bar.
                displayCutoutSafeExceptMaybeBars.top =
                        Math.max(statusBarSource.getFrame().bottom, displayCutoutSafe.top);
            }
            if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
                if (displayFrame.width() < displayFrame.height()) {
                    displayCutoutSafeExceptMaybeBars.top = MIN_Y;
@@ -131,7 +123,7 @@ public class WindowLayout {
                    && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
                    || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
                final Insets systemBarsInsets = state.calculateInsets(
                        displayFrame, WindowInsets.Type.systemBars(), requestedVisibleTypes);
                        displayFrame, systemBars(), requestedVisibleTypes);
                if (systemBarsInsets.left > 0) {
                    displayCutoutSafeExceptMaybeBars.left = MIN_X;
                }
@@ -145,13 +137,12 @@ public class WindowLayout {
                    displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
                }
            }
            if (type == TYPE_INPUT_METHOD) {
                final InsetsSource navSource = state.peekSource(ITYPE_NAVIGATION_BAR);
                if (navSource != null && navSource.calculateInsets(displayFrame, true).bottom > 0) {
            if (type == TYPE_INPUT_METHOD
                    && displayCutoutSafeExceptMaybeBars.bottom != MAX_Y
                    && state.calculateInsets(displayFrame, navigationBars(), true).bottom > 0) {
                // The IME can always extend under the bottom cutout if the navbar is there.
                displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
            }
            }
            final boolean attachedInParent = attachedWindowFrame != null && !layoutInScreen;

            // TYPE_BASE_APPLICATION windows are never considered floating here because they don't
+24 −28
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -14,11 +14,9 @@
 * limitations under the License.
 */

package com.android.server.wm;
package android.view;

import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
@@ -39,13 +37,6 @@ import android.app.WindowConfiguration;
import android.graphics.Insets;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.WindowInsets;
import android.view.WindowLayout;
import android.view.WindowManager;
import android.window.ClientWindowFrames;

import androidx.test.filters.SmallTest;
@@ -72,6 +63,11 @@ public class WindowLayoutTests {
            new Rect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT);
    private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0);

    private static final int ID_STATUS_BAR = InsetsSource.createId(
            null /* owner */, 0 /* index */, statusBars());
    private static final int ID_NAVIGATION_BAR = InsetsSource.createId(
            null /* owner */, 0 /* index */, navigationBars());

    private final WindowLayout mWindowLayout = new WindowLayout();
    private final ClientWindowFrames mFrames = new ClientWindowFrames();

@@ -90,9 +86,9 @@ public class WindowLayoutTests {
        mAttrs = new WindowManager.LayoutParams();
        mState = new InsetsState();
        mState.setDisplayFrame(new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
        mState.getOrCreateSource(ITYPE_STATUS_BAR, statusBars()).setFrame(
        mState.getOrCreateSource(ID_STATUS_BAR, statusBars()).setFrame(
                0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT);
        mState.getOrCreateSource(ITYPE_NAVIGATION_BAR, navigationBars()).setFrame(
        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars()).setFrame(
                0, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
        mState.getDisplayCutoutSafe(mDisplayCutoutSafe);
        mWindowBounds = new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
@@ -268,8 +264,8 @@ public class WindowLayoutTests {

    @Test
    public void fitInvisibleInsets() {
        mState.setSourceVisible(ITYPE_STATUS_BAR, false);
        mState.setSourceVisible(ITYPE_NAVIGATION_BAR, false);
        mState.setSourceVisible(ID_STATUS_BAR, false);
        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
        computeFrames();

        assertInsetByTopBottom(0, 0, mFrames.displayFrame);
@@ -279,8 +275,8 @@ public class WindowLayoutTests {

    @Test
    public void fitInvisibleInsetsIgnoringVisibility() {
        mState.setSourceVisible(ITYPE_STATUS_BAR, false);
        mState.setSourceVisible(ITYPE_NAVIGATION_BAR, false);
        mState.setSourceVisible(ID_STATUS_BAR, false);
        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
        mAttrs.setFitInsetsIgnoringVisibility(true);
        computeFrames();

@@ -324,11 +320,11 @@ public class WindowLayoutTests {
        mAttrs.setFitInsetsTypes(0);
        computeFrames();

        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.displayFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.parentFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.frame);
    }

@@ -365,17 +361,17 @@ public class WindowLayoutTests {
    @Test
    public void layoutInDisplayCutoutModeDefaultWithInvisibleSystemBars() {
        addDisplayCutout();
        mState.setSourceVisible(ITYPE_STATUS_BAR, false);
        mState.setSourceVisible(ITYPE_NAVIGATION_BAR, false);
        mState.setSourceVisible(ID_STATUS_BAR, false);
        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
        mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
        mAttrs.setFitInsetsTypes(0);
        computeFrames();

        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.displayFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.parentFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.frame);
    }

@@ -398,11 +394,11 @@ public class WindowLayoutTests {
        mAttrs.setFitInsetsTypes(0);
        computeFrames();

        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.displayFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.parentFrame);
        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                mFrames.frame);
    }