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

Commit 7ced0e24 authored by Yunfan Chen's avatar Yunfan Chen
Browse files

Refine the provide insets parameters

There're 3 different parameters trying to affect the insets provided by
a window and can be set independently but are related. This change will
make a new class InsetsFrameProvider to let the window set all the
information needed for the insets at the same place.

Besides, this change also extends the insets calculation logic to
support more use cases. With this, the bars can provide insets outside
of its window frame as well.

Test: atest DisplayPolicyLayoutTests
Bug: 161689946
Bug: 232044523
Merged-In: I7059b3a222745818b6852a288416e197e2afd7b2
Change-Id: I7059b3a222745818b6852a288416e197e2afd7b2
parent c8d7b7c6
Loading
Loading
Loading
Loading
+205 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.graphics.Insets;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Insets provided by a window.
 *
 * The insets frame will by default as the window frame size. If the providers are set, the
 * calculation result based on the source size will be used as the insets frame.
 * @hide
 */
public class InsetsFrameProvider implements Parcelable {

    /**
     * If specified in source field, the insets calculation will be based on the display frame.
     */
    public static final int SOURCE_DISPLAY = 0;

    /**
     * If specified in source field, the insets calculation will be based on the window bounds. The
     * container bounds can sometimes be different from the window frame. For example, when a task
     * bar needs the entire screen to be prepared to showing the apps, the window container can take
     * the entire display, or display area, but the window frame, as a result of the layout, will
     * stay small until it actually taking the entire display to draw their view.
     */
    public static final int SOURCE_CONTAINER_BOUNDS = 1;

    /**
     * If specified in source field, the insets calculation will be based on the window frame. This
     * is also the default value of the source.
     */
    public static final int SOURCE_FRAME = 2;

    private static final int HAS_INSETS_SIZE = 1;
    private static final int HAS_IME_INSETS_SIZE = 2;

    /**
     * The type of insets to provide.
     */
    public @InsetsState.InternalInsetsType int type;

    /**
     * The source of frame. By default, all adjustment will be based on the window frame, it
     * can be set to window bounds or display bounds instead.
     */
    public int source = SOURCE_FRAME;

    /**
     * The provided insets size based on the source frame. The result will be used as the insets
     * size to windows other than IME. Only one side should be set.
     *
     * For example, when the given source frame is (0, 0) - (100, 200), and the insetsSize is null,
     * the source frame will be directly used as the final insets frame. If the insetsSize is set to
     * (0, 0, 0, 50) instead, the insets frame will be a frame starting from the bottom side of the
     * source frame with height of 50, i.e., (0, 150) - (100, 200).
     */
    public Insets insetsSize = null;

    /**
     * The provided frame based on the source frame. The result will be used as the insets
     * size to IME window. Only one side should be set.
     */
    public Insets imeInsetsSize = null;

    public InsetsFrameProvider(int type) {
        this(type, SOURCE_FRAME, null, null);
    }

    public InsetsFrameProvider(int type, Insets insetsSize) {
        this(type, SOURCE_FRAME, insetsSize, insetsSize);
    }

    public InsetsFrameProvider(int type, Insets insetsSize, Insets imeInsetsSize) {
        this(type, SOURCE_FRAME, insetsSize, imeInsetsSize);
    }

    public InsetsFrameProvider(int type, int source, Insets insetsSize,
            Insets imeInsetsSize) {
        this.type = type;
        this.source = source;
        this.insetsSize = insetsSize;
        this.imeInsetsSize = imeInsetsSize;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(32);
        sb.append("InsetsFrameProvider: {");
        sb.append("type=").append(InsetsState.typeToString(type));
        sb.append(", source=");
        switch (source) {
            case SOURCE_DISPLAY:
                sb.append("SOURCE_DISPLAY");
                break;
            case SOURCE_CONTAINER_BOUNDS:
                sb.append("SOURCE_CONTAINER_BOUNDS Bounds");
                break;
            case SOURCE_FRAME:
                sb.append("SOURCE_FRAME");
                break;
        }
        if (insetsSize != null) {
            sb.append(", insetsSize=").append(insetsSize);
        }
        if (imeInsetsSize != null) {
            sb.append(", imeInsetsSize=").append(imeInsetsSize);
        }
        sb.append("}");
        return sb.toString();
    }

    public InsetsFrameProvider(Parcel in) {
        int insetsSizeModified = in.readInt();
        type = in.readInt();
        source = in.readInt();
        if ((insetsSizeModified & HAS_INSETS_SIZE) != 0) {
            insetsSize = Insets.CREATOR.createFromParcel(in);
        }
        if ((insetsSizeModified & HAS_IME_INSETS_SIZE) != 0) {
            imeInsetsSize = Insets.CREATOR.createFromParcel(in);
        }
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        int insetsSizeModified = 0;
        if (insetsSize != null) {
            insetsSizeModified |= HAS_INSETS_SIZE;
        }
        if (imeInsetsSize != null) {
            insetsSizeModified |= HAS_IME_INSETS_SIZE;
        }
        out.writeInt(insetsSizeModified);
        out.writeInt(type);
        out.writeInt(source);
        if (insetsSize != null) {
            insetsSize.writeToParcel(out, flags);
        }
        if (imeInsetsSize != null) {
            imeInsetsSize.writeToParcel(out, flags);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        InsetsFrameProvider other = (InsetsFrameProvider) o;
        return type == other.type && source == other.source
                && Objects.equals(insetsSize, other.insetsSize)
                && Objects.equals(imeInsetsSize, other.imeInsetsSize);
    }

    @Override
    public int hashCode() {
        int result = type;
        result = 31 * result + source;
        result = 31 * result + (insetsSize != null ? insetsSize.hashCode() : 0);
        result = 31 * result + (imeInsetsSize != null ? imeInsetsSize.hashCode() : 0);
        return result;
    }

    public static final @android.annotation.NonNull Parcelable.Creator<InsetsFrameProvider>
            CREATOR = new Parcelable.Creator<InsetsFrameProvider>() {
                @Override
                public InsetsFrameProvider createFromParcel(Parcel in) {
                    return new InsetsFrameProvider(in);
                }

                @Override
                public InsetsFrameProvider[] newArray(int size) {
                    return new InsetsFrameProvider[size];
                }
            };
}
+19 −103
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@@ -3603,34 +3602,17 @@ public interface WindowManager extends ViewManager {
        private boolean mFitInsetsIgnoringVisibility = false;

        /**
         * {@link InsetsState.InternalInsetsType}s to be applied to the window
         * If {@link #type} has the predefined insets (like {@link #TYPE_STATUS_BAR} or
         * {@link #TYPE_NAVIGATION_BAR}), this field will be ignored.
         * If set, the specified insets types will be provided by the window and the insets frame
         * will be calculated based on the provider's parameters. The insets types and the array
         * should not be modified after the window is added. If multiple layout parameters are
         * provided for different rotations in {@link LayoutParams#paramsForRotation}, the types in
         * the providedInsets array should be the same in all rotations, including the base one.
         * All other params can be adjusted at runtime.
         * See {@link InsetsFrameProvider}.
         *
         * <p>Note: provide only one inset corresponding to the window type (like
         * {@link InsetsState.InternalInsetsType#ITYPE_STATUS_BAR} or
         * {@link InsetsState.InternalInsetsType#ITYPE_NAVIGATION_BAR})</p>
         * @hide
         */
        public @InsetsState.InternalInsetsType int[] providesInsetsTypes;

        /**
         * If specified, the insets provided by this window will be our window frame minus the
         * insets specified by providedInternalInsets for each type. This should not be used
         * together with {@link WindowState#mGivenContentInsets}. If both of them are set, both will
         * be applied.
         *
         * @hide
         */
        public Insets[] providedInternalInsets;

        /**
         * If specified, the insets provided by this window for the IME will be our window frame
         * minus the insets specified by providedInternalImeInsets.
         *
         * @hide
         */
        public Insets[] providedInternalImeInsets;
        public InsetsFrameProvider[] providedInsets;

        /**
         * If specified, the frame that used to calculate relative {@link RoundedCorner} will be
@@ -4010,32 +3992,10 @@ public interface WindowManager extends ViewManager {
            out.writeBoolean(mFitInsetsIgnoringVisibility);
            out.writeBoolean(preferMinimalPostProcessing);
            out.writeInt(mBlurBehindRadius);
            if (providesInsetsTypes != null) {
                out.writeInt(providesInsetsTypes.length);
                out.writeIntArray(providesInsetsTypes);
            } else {
                out.writeInt(0);
            }
            if (providedInternalInsets != null) {
                out.writeInt(providedInternalInsets.length);
                out.writeTypedArray(providedInternalInsets, 0 /* parcelableFlags */);
            } else {
                out.writeInt(0);
            }
            if (providedInternalImeInsets != null) {
                out.writeInt(providedInternalImeInsets.length);
                out.writeTypedArray(providedInternalImeInsets, 0 /* parcelableFlags */);
            } else {
                out.writeInt(0);
            }
            out.writeBoolean(insetsRoundedCornerFrame);
            if (paramsForRotation != null) {
            out.writeTypedArray(providedInsets, 0 /* parcelableFlags */);
            checkNonRecursiveParams();
                out.writeInt(paramsForRotation.length);
            out.writeTypedArray(paramsForRotation, 0 /* parcelableFlags */);
            } else {
                out.writeInt(0);
            }
        }

        public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -4102,27 +4062,9 @@ public interface WindowManager extends ViewManager {
            mFitInsetsIgnoringVisibility = in.readBoolean();
            preferMinimalPostProcessing = in.readBoolean();
            mBlurBehindRadius = in.readInt();
            int insetsTypesLength = in.readInt();
            if (insetsTypesLength > 0) {
                providesInsetsTypes = new int[insetsTypesLength];
                in.readIntArray(providesInsetsTypes);
            }
            int providedInternalInsetsLength = in.readInt();
            if (providedInternalInsetsLength > 0) {
                providedInternalInsets = new Insets[providedInternalInsetsLength];
                in.readTypedArray(providedInternalInsets, Insets.CREATOR);
            }
            int providedInternalImeInsetsLength = in.readInt();
            if (providedInternalImeInsetsLength > 0) {
                providedInternalImeInsets = new Insets[providedInternalImeInsetsLength];
                in.readTypedArray(providedInternalImeInsets, Insets.CREATOR);
            }
            insetsRoundedCornerFrame = in.readBoolean();
            int paramsForRotationLength = in.readInt();
            if (paramsForRotationLength > 0) {
                paramsForRotation = new LayoutParams[paramsForRotationLength];
                in.readTypedArray(paramsForRotation, LayoutParams.CREATOR);
            }
            providedInsets = in.createTypedArray(InsetsFrameProvider.CREATOR);
            paramsForRotation = in.createTypedArray(LayoutParams.CREATOR);
        }

        @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -4414,18 +4356,8 @@ public interface WindowManager extends ViewManager {
                changes |= LAYOUT_CHANGED;
            }

            if (!Arrays.equals(providesInsetsTypes, o.providesInsetsTypes)) {
                providesInsetsTypes = o.providesInsetsTypes;
                changes |= LAYOUT_CHANGED;
            }

            if (!Arrays.equals(providedInternalInsets, o.providedInternalInsets)) {
                providedInternalInsets = o.providedInternalInsets;
                changes |= LAYOUT_CHANGED;
            }

            if (!Arrays.equals(providedInternalImeInsets, o.providedInternalImeInsets)) {
                providedInternalImeInsets = o.providedInternalImeInsets;
            if (!Arrays.equals(providedInsets, o.providedInsets)) {
                providedInsets = o.providedInsets;
                changes |= LAYOUT_CHANGED;
            }

@@ -4627,28 +4559,12 @@ public interface WindowManager extends ViewManager {
                sb.append(System.lineSeparator());
                sb.append(prefix).append("  fitIgnoreVis");
            }
            if (providesInsetsTypes != null) {
                sb.append(System.lineSeparator());
                sb.append(prefix).append("  insetsTypes=");
                for (int i = 0; i < providesInsetsTypes.length; ++i) {
                    if (i > 0) sb.append(' ');
                    sb.append(InsetsState.typeToString(providesInsetsTypes[i]));
                }
            }
            if (providedInternalInsets != null) {
                sb.append(System.lineSeparator());
                sb.append(" providedInternalInsets=");
                for (int i = 0; i < providedInternalInsets.length; ++i) {
                    if (i > 0) sb.append(' ');
                    sb.append((providedInternalInsets[i]));
                }
            }
            if (providedInternalImeInsets != null) {
            if (providedInsets != null) {
                sb.append(System.lineSeparator());
                sb.append(" providedInternalImeInsets=");
                for (int i = 0; i < providedInternalImeInsets.length; ++i) {
                sb.append(" providedInsets=");
                for (int i = 0; i < providedInsets.length; ++i) {
                    if (i > 0) sb.append(' ');
                    sb.append((providedInternalImeInsets[i]));
                    sb.append((providedInsets[i]));
                }
            }
            if (insetsRoundedCornerFrame) {
+6 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.InsetsController;
import android.view.InsetsFrameProvider;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -105,7 +106,11 @@ public class WindowManagerWrapper {
     */
    public void setProvidesInsetsTypes(WindowManager.LayoutParams params,
            int[] providesInsetsTypes) {
        params.providesInsetsTypes = providesInsetsTypes;
        final int length = providesInsetsTypes.length;
        params.providedInsets = new InsetsFrameProvider[length];
        for (int i = 0; i < length; i++) {
            params.providedInsets[i] = new InsetsFrameProvider(providesInsetsTypes[i]);
        }
    }

    /**
+7 −5
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InsetsState;
import android.view.InsetsFrameProvider;
import android.view.InsetsState.InternalInsetsType;
import android.view.InsetsVisibilities;
import android.view.KeyEvent;
@@ -1654,12 +1654,14 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        lp.gravity = gravity;
        lp.providedInternalInsets = new Insets[InsetsState.SIZE];
        if (insetsHeight != -1) {
            lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] =
                    Insets.of(0, height - insetsHeight, 0, 0);
            lp.providedInsets = new InsetsFrameProvider[] {
                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight))
            };
        } else {
            lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] = null;
            lp.providedInsets = new InsetsFrameProvider[] {
                    new InsetsFrameProvider(ITYPE_NAVIGATION_BAR)
            };
        }
        lp.token = new Binder();
        lp.accessibilityTitle = userContext.getString(R.string.nav_bar);
+93 −92

File changed.

Preview size limit exceeded, changes collapsed.

Loading