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

Commit 56aad85b authored by Yunfan Chen's avatar Yunfan Chen Committed by Android (Google) Code Review
Browse files

Merge "Layout status/nav bar and decor window as normal window" into sc-v2-dev

parents a0b223a6 fce2e99c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -284,6 +284,21 @@ public final class ViewRootImpl implements ViewParent,
     */
    private static final int SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS = 2500;

    /**
     * If set to {@code true}, the new logic to layout system bars as normal window and to use
     * layout result to get insets will be applied. Otherwise, the old hard-coded window logic will
     * be applied.
     */
    private static final String USE_FLEXIBLE_INSETS = "persist.debug.flexible_insets";

    /**
     * A flag to indicate to use the new generalized insets window logic, or the old hard-coded
     * insets window layout logic.
     * {@hide}
     */
    public static final boolean INSETS_LAYOUT_GENERALIZATION =
            SystemProperties.getBoolean(USE_FLEXIBLE_INSETS, false);

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();

+66 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import android.content.ClipData;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@@ -3467,6 +3468,22 @@ public interface WindowManager extends ViewManager {
         */
        public @InsetsState.InternalInsetsType int[] providesInsetsTypes;

        /**
         * If specified, the insets provided by this window will be our window frame minus the
         * insets specified by providedInternalInsets.
         *
         * @hide
         */
        public Insets providedInternalInsets = Insets.NONE;

        /**
         * {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
         * This will make layout during rotation change smoothly.
         *
         * @hide
         */
        public LayoutParams[] paramsForRotation;

        /**
         * Specifies types of insets that this window should avoid overlapping during layout.
         *
@@ -3566,6 +3583,18 @@ public interface WindowManager extends ViewManager {
            return mFitInsetsIgnoringVisibility;
        }

        private void checkNonRecursiveParams() {
            if (paramsForRotation == null) {
                return;
            }
            for (int i = paramsForRotation.length - 1; i >= 0; i--) {
                if (paramsForRotation[i].paramsForRotation != null) {
                    throw new IllegalArgumentException(
                            "Params cannot contain params recursively.");
                }
            }
        }

        public LayoutParams() {
            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            type = TYPE_APPLICATION;
@@ -3818,6 +3847,14 @@ public interface WindowManager extends ViewManager {
            } else {
                out.writeInt(0);
            }
            providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */);
            if (paramsForRotation != null) {
                checkNonRecursiveParams();
                out.writeInt(paramsForRotation.length);
                out.writeTypedArray(paramsForRotation, 0 /* parcelableFlags */);
            } else {
                out.writeInt(0);
            }
        }

        public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -3887,6 +3924,12 @@ public interface WindowManager extends ViewManager {
                providesInsetsTypes = new int[insetsTypesLength];
                in.readIntArray(providesInsetsTypes);
            }
            providedInternalInsets = Insets.CREATOR.createFromParcel(in);
            int paramsForRotationLength = in.readInt();
            if (paramsForRotationLength > 0) {
                paramsForRotation = new LayoutParams[paramsForRotationLength];
                in.readTypedArray(paramsForRotation, LayoutParams.CREATOR);
            }
        }

        @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -4169,6 +4212,17 @@ public interface WindowManager extends ViewManager {
                changes |= LAYOUT_CHANGED;
            }

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

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

            return changes;
        }

@@ -4356,6 +4410,18 @@ public interface WindowManager extends ViewManager {
                    sb.append(InsetsState.typeToString(providesInsetsTypes[i]));
                }
            }
            if (!providedInternalInsets.equals(Insets.NONE)) {
                sb.append(" providedInternalInsets=");
                sb.append(providedInternalInsets);
            }
            if (paramsForRotation != null && paramsForRotation.length != 0) {
                sb.append(System.lineSeparator());
                sb.append(prefix).append("  paramsForRotation=");
                for (int i = 0; i < paramsForRotation.length; ++i) {
                    if (i > 0) sb.append(' ');
                    sb.append(paramsForRotation[i].toString());
                }
            }

            sb.append('}');
            return sb.toString();
+99 −31
Original line number Diff line number Diff line
@@ -23,10 +23,12 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.containsType;
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
@@ -67,6 +69,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -199,6 +202,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,

    private Bundle mSavedState;
    private NavigationBarView mNavigationBarView;
    private NavigationBarFrame mFrame;

    private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;

@@ -489,34 +493,17 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
    }

    public View createView(Bundle savedState) {
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        lp.token = new Binder();
        lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        lp.windowAnimations = 0;
        lp.setTitle("NavigationBar" + mContext.getDisplayId());
        lp.setFitInsetsTypes(0 /* types */);
        lp.setTrustedOverlay();

        NavigationBarFrame frame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
        mFrame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
                R.layout.navigation_bar_window, null);
        View barView = LayoutInflater.from(frame.getContext()).inflate(
                R.layout.navigation_bar, frame);
        View barView = LayoutInflater.from(mFrame.getContext()).inflate(
                R.layout.navigation_bar, mFrame);
        barView.addOnAttachStateChangeListener(this);
        mNavigationBarView = barView.findViewById(R.id.navigation_bar_view);

        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + barView);
        mContext.getSystemService(WindowManager.class).addView(frame, lp);
        mContext.getSystemService(WindowManager.class).addView(mFrame,
                getBarLayoutParams(mContext.getResources().getConfiguration().windowConfiguration
                        .getRotation()));
        mDisplayId = mContext.getDisplayId();
        mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;

@@ -670,6 +657,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
        mHandler.removeCallbacks(mAutoDim);
        mHandler.removeCallbacks(mOnVariableDurationHomeLongClick);
        mHandler.removeCallbacks(mEnableLayoutTransitions);
        mFrame = null;
        mNavigationBarView = null;
        mOrientationHandle = null;
    }
@@ -688,6 +676,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
     * Called when a non-reloading configuration change happens and we need to update.
     */
    public void onConfigurationChanged(Configuration newConfig) {
        final int rotation = newConfig.windowConfiguration.getRotation();
        final Locale locale = mContext.getResources().getConfiguration().locale;
        final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
        if (!locale.equals(mLocale) || ld != mLayoutDirection) {
@@ -701,9 +690,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
            refreshLayout(ld);
        }

        repositionNavigationBar();
        repositionNavigationBar(rotation);
        if (canShowSecondaryHandle()) {
            int rotation = newConfig.windowConfiguration.getRotation();
            if (rotation != mCurrentRotation) {
                mCurrentRotation = rotation;
                orientSecondaryHomeHandle();
@@ -1068,13 +1056,12 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
                || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
    }

    private void repositionNavigationBar() {
        if (!mNavigationBarView.isAttachedToWindow()) return;
    private void repositionNavigationBar(int rotation) {
        if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;

        prepareNavigationBarView();

        mWindowManager.updateViewLayout((View) mNavigationBarView.getParent(),
                ((View) mNavigationBarView.getParent()).getLayoutParams());
        mWindowManager.updateViewLayout(mFrame, getBarLayoutParams(rotation));
    }

    private void updateScreenPinningGestures() {
@@ -1509,13 +1496,94 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
    private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener =
            this::updateAccessibilityServicesState;

    private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
        WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
        lp.paramsForRotation = new WindowManager.LayoutParams[4];
        for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
            lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);
        }
        return lp;
    }

    private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
        int width = WindowManager.LayoutParams.MATCH_PARENT;
        int height = WindowManager.LayoutParams.MATCH_PARENT;
        int insetsHeight = -1;
        int gravity = Gravity.BOTTOM;
        if (INSETS_LAYOUT_GENERALIZATION) {
            boolean navBarCanMove = true;
            if (mWindowManager != null && mWindowManager.getCurrentWindowMetrics() != null) {
                Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
                navBarCanMove = displaySize.width() != displaySize.height()
                        && mContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_navBarCanMove);
            }
            if (!navBarCanMove) {
                height = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.navigation_bar_frame_height);
                insetsHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.navigation_bar_height);
            } else {
                switch (rotation) {
                    case ROTATION_UNDEFINED:
                    case Surface.ROTATION_0:
                    case Surface.ROTATION_180:
                        height = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_frame_height);
                        insetsHeight = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_height);
                        break;
                    case Surface.ROTATION_90:
                        gravity = Gravity.RIGHT;
                        width = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_width);
                        break;
                    case Surface.ROTATION_270:
                        gravity = Gravity.LEFT;
                        width = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_width);
                        break;
                }
            }
        }
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                width,
                height,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        if (INSETS_LAYOUT_GENERALIZATION) {
            lp.gravity = gravity;
            if (insetsHeight != -1) {
                lp.providedInternalInsets = Insets.of(0, height - insetsHeight, 0, 0);
            } else {
                lp.providedInternalInsets = Insets.NONE;
            }
        }
        lp.token = new Binder();
        lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        lp.windowAnimations = 0;
        lp.setTitle("NavigationBar" + mContext.getDisplayId());
        lp.setFitInsetsTypes(0 /* types */);
        lp.setTrustedOverlay();
        return lp;
    }

    private boolean canShowSecondaryHandle() {
        return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null;
    }

    private final Consumer<Integer> mRotationWatcher = rotation -> {
        if (mNavigationBarView.needsReorient(rotation)) {
            repositionNavigationBar();
        if (mNavigationBarView != null
                && mNavigationBarView.needsReorient(rotation)) {
            repositionNavigationBar(rotation);
        }
    };

+61 −15
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.phone;

import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -34,6 +36,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.Gravity;
import android.view.IWindowManager;
import android.view.Surface;
import android.view.ViewGroup;
import android.view.WindowManager;

@@ -118,21 +121,7 @@ public class StatusBarWindowController {
        // Now that the status bar window encompasses the sliding panel and its
        // translucent backdrop, the entire thing is made TRANSLUCENT and is
        // hardware-accelerated.
        mLp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                mBarHeight,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                PixelFormat.TRANSLUCENT);
        mLp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        mLp.token = new Binder();
        mLp.gravity = Gravity.TOP;
        mLp.setFitInsetsTypes(0 /* types */);
        mLp.setTitle("StatusBar");
        mLp.packageName = mContext.getPackageName();
        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        mLp = getBarLayoutParams(mContext.getDisplay().getRotation());

        mWindowManager.addView(mStatusBarView, mLp);
        mLpChanged.copyFrom(mLp);
@@ -141,6 +130,63 @@ public class StatusBarWindowController {
        calculateStatusBarLocationsForAllRotations();
    }

    private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
        WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
        lp.paramsForRotation = new WindowManager.LayoutParams[4];
        for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
            lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);
        }
        return lp;
    }

    private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
        int height = mBarHeight;
        if (INSETS_LAYOUT_GENERALIZATION) {
            Rect displayBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
            int defaultAndUpsideDownHeight;
            int theOtherHeight;
            if (displayBounds.width() > displayBounds.height()) {
                defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.status_bar_height_landscape);
                theOtherHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.status_bar_height_portrait);
            } else {
                defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.status_bar_height_portrait);
                theOtherHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.status_bar_height_landscape);
            }
            switch (rotation) {
                case ROTATION_UNDEFINED:
                case Surface.ROTATION_0:
                case Surface.ROTATION_180:
                    height = defaultAndUpsideDownHeight;
                    break;
                case Surface.ROTATION_90:
                case Surface.ROTATION_270:
                    height = theOtherHeight;
                    break;
            }
        }
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                height,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                PixelFormat.TRANSLUCENT);
        lp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        lp.token = new Binder();
        lp.gravity = Gravity.TOP;
        lp.setFitInsetsTypes(0 /* types */);
        lp.setTitle("StatusBar");
        lp.packageName = mContext.getPackageName();
        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        return lp;

    }

    private void calculateStatusBarLocationsForAllRotations() {
        Rect[] bounds = new Rect[4];
        bounds[0] = mContentInsetsProvider
+206 −49

File changed.

Preview size limit exceeded, changes collapsed.

Loading