Loading services/core/java/com/android/server/wm/InsetsPolicy.java +136 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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--) { Loading Loading @@ -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. Loading services/core/java/com/android/server/wm/InsetsStateController.java +4 −140 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; } Loading @@ -248,6 +108,10 @@ class InsetsStateController { return result; } ArrayMap<Integer, InsetsSourceProvider> getSourceProviders() { return mProviders; } /** * @return The provider of a specific type. */ Loading services/core/java/com/android/server/wm/Task.java +1 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading services/core/java/com/android/server/wm/WindowState.java +32 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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; Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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 Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +136 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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--) { Loading Loading @@ -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. Loading
services/core/java/com/android/server/wm/InsetsStateController.java +4 −140 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; } Loading @@ -248,6 +108,10 @@ class InsetsStateController { return result; } ArrayMap<Integer, InsetsSourceProvider> getSourceProviders() { return mProviders; } /** * @return The provider of a specific type. */ Loading
services/core/java/com/android/server/wm/Task.java +1 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading
services/core/java/com/android/server/wm/WindowState.java +32 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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; Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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