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

Commit 1b49dc77 authored by Gaurav Bhola's avatar Gaurav Bhola Committed by Android (Google) Code Review
Browse files

Merge "Relocate the getInsetsForWindow logic inside WindowState."

parents 8fe4c2af 781f435c
Loading
Loading
Loading
Loading
+136 −9
Original line number Diff line number Diff line
@@ -19,24 +19,36 @@ package com.android.server.wm;
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.StatusBarManager;
import android.app.WindowConfiguration;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
@@ -235,10 +247,11 @@ class InsetsPolicy {
    }

    /**
     * @see InsetsStateController#getInsetsForWindow
     * Adjusts the sources in {@code originalState} to account for things like transient bars, IME
     * & rounded corners.
     */
    InsetsState getInsetsForWindow(WindowState target, boolean includesTransient) {
        final InsetsState originalState = mStateController.getInsetsForWindow(target);
    InsetsState adjustInsetsForWindow(WindowState target, InsetsState originalState,
            boolean includesTransient) {
        InsetsState state;
        if (!includesTransient) {
            state = adjustVisibilityForTransientTypes(originalState);
@@ -249,19 +262,133 @@ class InsetsPolicy {
        return adjustInsetsForRoundedCorners(target, state, state == originalState);
    }

    InsetsState getInsetsForWindow(WindowState target) {
        return getInsetsForWindow(target, false);
    InsetsState adjustInsetsForWindow(WindowState target, InsetsState originalState) {
        return adjustInsetsForWindow(target, originalState, false);
    }


    /**
     * @see InsetsStateController#getInsetsForWindowMetrics
     * @see WindowState#getInsetsState()
     */
    InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
        final InsetsState originalState = mStateController.getInsetsForWindowMetrics(attrs);
        final @InternalInsetsType int type = getInsetsTypeForLayoutParams(attrs);
        final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
        if (token != null) {
            final InsetsState rotatedState = token.getFixedRotationTransformInsetsState();
            if (rotatedState != null) {
                return rotatedState;
            }
        }
        final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
        // Always use windowing mode fullscreen when get insets for window metrics to make sure it
        // contains all insets types.
        final InsetsState originalState = mDisplayContent.getInsetsPolicy()
                .enforceInsetsPolicyForTarget(type, WINDOWING_MODE_FULLSCREEN, alwaysOnTop,
                        mStateController.getRawInsetsState());
        return adjustVisibilityForTransientTypes(originalState);
    }

    private static @InternalInsetsType int getInsetsTypeForLayoutParams(
            WindowManager.LayoutParams attrs) {
        @WindowManager.LayoutParams.WindowType int type = attrs.type;
        switch (type) {
            case TYPE_STATUS_BAR:
                return ITYPE_STATUS_BAR;
            case TYPE_NAVIGATION_BAR:
                return ITYPE_NAVIGATION_BAR;
            case TYPE_INPUT_METHOD:
                return ITYPE_IME;
        }

        // If not one of the types above, check whether an internal inset mapping is specified.
        if (attrs.providesInsetsTypes != null) {
            for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) {
                switch (insetsType) {
                    case ITYPE_STATUS_BAR:
                    case ITYPE_NAVIGATION_BAR:
                    case ITYPE_CLIMATE_BAR:
                    case ITYPE_EXTRA_NAVIGATION_BAR:
                        return insetsType;
                }
            }
        }

        return ITYPE_INVALID;
    }


    /**
     * Modifies the given {@code state} according to the {@code type} (Inset type) provided by
     * the target.
     * When performing layout of the target or dispatching insets to the target, we need to exclude
     * sources which should not be visible to the target. e.g., the source which represents the
     * target window itself, and the IME source when the target is above IME. We also need to
     * exclude certain types of insets source for client within specific windowing modes.
     *
     * @param type the inset type provided by the target
     * @param windowingMode the windowing mode of the target
     * @param isAlwaysOnTop is the target always on top
     * @param state the input inset state containing all the sources
     * @return The state stripped of the necessary information.
     */
    InsetsState enforceInsetsPolicyForTarget(@InternalInsetsType int type,
            @WindowConfiguration.WindowingMode int windowingMode, boolean isAlwaysOnTop,
            InsetsState state) {
        boolean stateCopied = false;

        if (type != ITYPE_INVALID) {
            state = new InsetsState(state);
            stateCopied = true;
            state.removeSource(type);

            // Navigation bar doesn't get influenced by anything else
            if (type == ITYPE_NAVIGATION_BAR || type == ITYPE_EXTRA_NAVIGATION_BAR) {
                state.removeSource(ITYPE_IME);
                state.removeSource(ITYPE_STATUS_BAR);
                state.removeSource(ITYPE_CLIMATE_BAR);
                state.removeSource(ITYPE_CAPTION_BAR);
                state.removeSource(ITYPE_NAVIGATION_BAR);
                state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
            }

            // Status bar doesn't get influenced by caption bar
            if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) {
                state.removeSource(ITYPE_CAPTION_BAR);
            }

            // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
            if (type == ITYPE_IME) {
                ArrayMap<Integer, InsetsSourceProvider> providers = mStateController
                        .getSourceProviders();
                for (int i = providers.size() - 1; i >= 0; i--) {
                    InsetsSourceProvider otherProvider = providers.valueAt(i);
                    if (otherProvider.overridesImeFrame()) {
                        InsetsSource override =
                                new InsetsSource(
                                        state.getSource(otherProvider.getSource().getType()));
                        override.setFrame(otherProvider.getImeOverrideFrame());
                        state.addSource(override);
                    }
                }
            }
        }

        if (WindowConfiguration.isFloating(windowingMode)
                || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
            if (!stateCopied) {
                state = new InsetsState(state);
                stateCopied = true;
            }
            state.removeSource(ITYPE_STATUS_BAR);
            state.removeSource(ITYPE_NAVIGATION_BAR);
            state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
            if (windowingMode == WINDOWING_MODE_PINNED) {
                state.removeSource(ITYPE_IME);
            }
        }

        return state;
    }

    private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) {
        InsetsState state = originalState;
        for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
@@ -644,7 +771,7 @@ class InsetsPolicy {
                }
                mAnimatingShown = show;

                final InsetsState state = getInsetsForWindow(mFocusedWin);
                final InsetsState state = mFocusedWin.getInsetsState();

                // We are about to playing the default animation. Passing a null frame indicates
                // the controlled types should be animated regardless of the frame.
+4 −140
Original line number Diff line number Diff line
@@ -16,30 +16,20 @@

package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
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.mandatorySystemGestures;
import static android.view.WindowInsets.Type.systemGestures;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect;
import android.os.Trace;
import android.util.ArrayMap;
@@ -49,8 +39,6 @@ import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams.WindowType;

import com.android.internal.protolog.common.ProtoLog;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -103,134 +91,6 @@ class InsetsStateController {
        mDisplayContent = displayContent;
    }

    /**
     * Gets the insets state from the perspective of the target. When performing layout of the
     * target or dispatching insets to the target, we need to exclude sources which should not be
     * visible to the target. e.g., the source which represents the target window itself, and the
     * IME source when the target is above IME. We also need to exclude certain types of insets
     * source for client within specific windowing modes.
     * This is to get the insets for a window layout on the screen. If the window is not there, use
     * the {@link #getInsetsForWindowMetrics} to get insets instead.
     *
     * @param target The window associate with the perspective.
     * @return The state stripped of the necessary information.
     */
    InsetsState getInsetsForWindow(@NonNull WindowState target) {
        final InsetsState rotatedState = target.mToken.getFixedRotationTransformInsetsState();
        if (rotatedState != null) {
            return rotatedState;
        }
        final InsetsSourceProvider provider = target.getControllableInsetProvider();
        final @InternalInsetsType int type = provider != null
                ? provider.getSource().getType() : ITYPE_INVALID;
        return getInsetsForTarget(type, target.getWindowingMode(), target.isAlwaysOnTop(),
                target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() :
                        (target.mAttrs.receiveInsetsIgnoringZOrder ? mState :
                         target.mAboveInsetsState));
    }

    InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
        final @InternalInsetsType int type = getInsetsTypeForLayoutParams(attrs);
        final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
        if (token != null) {
            final InsetsState rotatedState = token.getFixedRotationTransformInsetsState();
            if (rotatedState != null) {
                return rotatedState;
            }
        }
        final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
        // Always use windowing mode fullscreen when get insets for window metrics to make sure it
        // contains all insets types.
        return getInsetsForTarget(type, WINDOWING_MODE_FULLSCREEN, alwaysOnTop, mState);
    }

    private static @InternalInsetsType
            int getInsetsTypeForLayoutParams(WindowManager.LayoutParams attrs) {
        @WindowType int type = attrs.type;
        switch (type) {
            case TYPE_STATUS_BAR:
                return ITYPE_STATUS_BAR;
            case TYPE_NAVIGATION_BAR:
                return ITYPE_NAVIGATION_BAR;
            case TYPE_INPUT_METHOD:
                return ITYPE_IME;
        }

        // If not one of the types above, check whether an internal inset mapping is specified.
        if (attrs.providesInsetsTypes != null) {
            for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) {
                switch (insetsType) {
                    case ITYPE_STATUS_BAR:
                    case ITYPE_NAVIGATION_BAR:
                    case ITYPE_CLIMATE_BAR:
                    case ITYPE_EXTRA_NAVIGATION_BAR:
                        return insetsType;
                }
            }
        }

        return ITYPE_INVALID;
    }

    /**
     * @see #getInsetsForWindow
     * @see #getInsetsForWindowMetrics
     */
    private InsetsState getInsetsForTarget(@InternalInsetsType int type,
            @WindowingMode int windowingMode, boolean isAlwaysOnTop, InsetsState state) {
        boolean stateCopied = false;

        if (type != ITYPE_INVALID) {
            state = new InsetsState(state);
            stateCopied = true;
            state.removeSource(type);

            // Navigation bar doesn't get influenced by anything else
            if (type == ITYPE_NAVIGATION_BAR || type == ITYPE_EXTRA_NAVIGATION_BAR) {
                state.removeSource(ITYPE_STATUS_BAR);
                state.removeSource(ITYPE_CLIMATE_BAR);
                state.removeSource(ITYPE_CAPTION_BAR);
                state.removeSource(ITYPE_NAVIGATION_BAR);
                state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
            }

            // Status bar doesn't get influenced by caption bar
            if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) {
                state.removeSource(ITYPE_CAPTION_BAR);
            }

            // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
            if (type == ITYPE_IME) {
                for (int i = mProviders.size() - 1; i >= 0; i--) {
                    InsetsSourceProvider otherProvider = mProviders.valueAt(i);
                    if (otherProvider.overridesImeFrame()) {
                        InsetsSource override =
                                new InsetsSource(
                                        state.getSource(otherProvider.getSource().getType()));
                        override.setFrame(otherProvider.getImeOverrideFrame());
                        state.addSource(override);
                    }
                }
            }
        }

        if (WindowConfiguration.isFloating(windowingMode)
                || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
            if (!stateCopied) {
                state = new InsetsState(state);
                stateCopied = true;
            }
            state.removeSource(ITYPE_STATUS_BAR);
            state.removeSource(ITYPE_NAVIGATION_BAR);
            state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
            if (windowingMode == WINDOWING_MODE_PINNED) {
                state.removeSource(ITYPE_IME);
            }
        }

        return state;
    }

    InsetsState getRawInsetsState() {
        return mState;
    }
@@ -248,6 +108,10 @@ class InsetsStateController {
        return result;
    }

    ArrayMap<Integer, InsetsSourceProvider> getSourceProviders() {
        return mProviders;
    }

    /**
     * @return The provider of a specific type.
     */
+1 −2
Original line number Diff line number Diff line
@@ -6582,8 +6582,7 @@ class Task extends TaskFragment {
            return;
        }
        if (mOverlayHost != null) {
            final InsetsState s = getDisplayContent().getInsetsPolicy()
                .getInsetsForWindow(originalChange, true);
            final InsetsState s = originalChange.getInsetsState(true);
            getBounds(mTmpRect);
            mOverlayHost.dispatchInsetsChanged(s, mTmpRect);
        }
+32 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.SurfaceControl.Transaction;
import static android.view.SurfaceControl.getGlobalTransaction;
@@ -1646,12 +1647,40 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return super.getMaxBounds();
    }

    /**
     * See {@link WindowState#getInsetsState(boolean)}
     */
    InsetsState getInsetsState() {
        return getInsetsState(false);
    }

    /**
     * Returns the insets state for the window. Its sources may be the copies with visibility
     * modification according to the state of transient bars.
     * This is to get the insets for a window layout on the screen. If the window is not there, use
     * the {@link InsetsPolicy#getInsetsForWindowMetrics} to get insets instead.
     * @param includeTransient whether or not the transient types should be included in the
     *                         insets state.
     */
    InsetsState getInsetsState() {
        return getDisplayContent().getInsetsPolicy().getInsetsForWindow(this);
    InsetsState getInsetsState(boolean includeTransient) {
        final InsetsState rotatedState = mToken.getFixedRotationTransformInsetsState();
        final InsetsPolicy insetsPolicy = getDisplayContent().getInsetsPolicy();
        if (rotatedState != null) {
            return insetsPolicy.adjustInsetsForWindow(this, rotatedState);
        }
        final InsetsSourceProvider provider = getControllableInsetProvider();
        final InsetsStateController insetsStateController = getDisplayContent()
                .getInsetsStateController();
        final @InternalInsetsType int insetTypeProvidedByWindow = provider != null
                ? provider.getSource().getType() : ITYPE_INVALID;
        final InsetsState rawInsetsState = getFrozenInsetsState() != null
                ? getFrozenInsetsState() : (mAttrs.receiveInsetsIgnoringZOrder
                ? insetsStateController.getRawInsetsState() : mAboveInsetsState);
        final InsetsState insetsStateForWindow = insetsPolicy
                .enforceInsetsPolicyForTarget(insetTypeProvidedByWindow,
                        getWindowingMode(), isAlwaysOnTop(), rawInsetsState);
        return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow,
                includeTransient);
    }

    /**
@@ -5666,7 +5695,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     * into the state of the control target.
     *
     * @param insetProvider the provider which should not be visible to the client.
     * @see InsetsStateController#getInsetsForWindow(WindowState)
     * @see #getInsetsState()
     */
    void setControllableInsetProvider(InsetsSourceProvider insetProvider) {
        mControllableInsetProvider = insetProvider;
+2 −2
Original line number Diff line number Diff line
@@ -3059,7 +3059,7 @@ public class ActivityRecordTests extends WindowTestsBase {
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.updateImeInputAndControlTarget(app);

        InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
        InsetsState state = app.getInsetsState();
        assertFalse(state.getSource(ITYPE_IME).isVisible());
        assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty());

@@ -3079,7 +3079,7 @@ public class ActivityRecordTests extends WindowTestsBase {

        // Verify when IME is visible and the app can receive the right IME insets from policy.
        makeWindowVisibleAndDrawn(app, mImeWindow);
        state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
        state = app.getInsetsState();
        assertTrue(state.getSource(ITYPE_IME).isVisible());
        assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
    }
Loading