diff options
5 files changed, 75 insertions, 8 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index e890bda097f1..db89d9588507 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -643,6 +643,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } /** + * @see ViewRootImpl#updateCompatSysUiVisibility(int, boolean, boolean) + */ + public void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible, + boolean hasControl) { + mViewRoot.updateCompatSysUiVisibility(type, visible, hasControl); + } + + /** * Called when current window gains focus. */ public void onWindowFocusGained() { diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 8a1b45a3a411..35a82b8bfd54 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -123,12 +123,19 @@ public class InsetsSourceConsumer { } boolean applyLocalVisibilityOverride() { + final boolean isVisible = mState.getSource(mType).isVisible(); + final boolean hasControl = mSourceControl != null; + + // We still need to let the legacy app know the visibility change even if we don't have the + // control. + mController.updateCompatSysUiVisibility( + mType, hasControl ? mRequestedVisible : isVisible, hasControl); // If we don't have control, we are not able to change the visibility. - if (mSourceControl == null) { + if (!hasControl) { return false; } - if (mState.getSource(mType).isVisible() == mRequestedVisible) { + if (isVisible == mRequestedVisible) { return false; } mState.getSource(mType).setVisible(mRequestedVisible); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2d1d78f158e7..32622233d81e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -18,6 +18,8 @@ package android.view; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; +import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.View.PFLAG_DRAW_ANIMATION; import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; @@ -105,6 +107,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.TypedValue; +import android.view.InsetsState.InternalInsetsType; import android.view.Surface.OutOfResourcesException; import android.view.SurfaceControl.Transaction; import android.view.View.AttachInfo; @@ -417,6 +420,7 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage final View.AttachInfo mAttachInfo; + final SystemUiVisibilityInfo mCompatibleVisibilityInfo; InputQueue.Callback mInputQueueCallback; InputQueue mInputQueue; @UnsupportedAppUsage @@ -674,6 +678,7 @@ public final class ViewRootImpl implements ViewParent, mAdded = false; mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); + mCompatibleVisibilityInfo = new SystemUiVisibilityInfo(); mAccessibilityManager = AccessibilityManager.getInstance(context); mAccessibilityManager.addAccessibilityStateChangeListener( mAccessibilityInteractionConnectionManager, mHandler); @@ -1862,6 +1867,9 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mSystemUiVisibility &= ~mAttachInfo.mDisabledSystemUiVisibility; WindowManager.LayoutParams params = mWindowAttributes; mAttachInfo.mSystemUiVisibility |= getImpliedSystemUiVisibility(params); + mCompatibleVisibilityInfo.globalVisibility = + (mCompatibleVisibilityInfo.globalVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE) + | (mAttachInfo.mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); if (mAttachInfo.mKeepScreenOn != oldScreenOn || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) { @@ -1887,6 +1895,38 @@ public final class ViewRootImpl implements ViewParent, return vis; } + /** + * Update the compatible system UI visibility for dispatching it to the legacy app. + * + * @param type Indicates which type of the insets source we are handling. + * @param visible True if the insets source is visible. + * @param hasControl True if we can control the insets source. + */ + void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible, + boolean hasControl) { + if ((type != ITYPE_STATUS_BAR && type != ITYPE_NAVIGATION_BAR) + || ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { + return; + } + final SystemUiVisibilityInfo info = mCompatibleVisibilityInfo; + final int systemUiFlag = type == ITYPE_STATUS_BAR + ? View.SYSTEM_UI_FLAG_FULLSCREEN + : View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + final boolean wasVisible = (info.globalVisibility & systemUiFlag) == 0; + if (visible) { + info.globalVisibility &= ~systemUiFlag; + if (!wasVisible && hasControl) { + // The local system UI visibility can only be cleared while we have the control. + info.localChanges |= systemUiFlag; + } + } else { + info.globalVisibility |= systemUiFlag; + } + if (mAttachInfo.mGlobalSystemUiVisibility != info.globalVisibility) { + scheduleTraversals(); + } + } + @VisibleForTesting public static void adjustLayoutParamsForCompatibility(WindowManager.LayoutParams inOutParams) { if (sNewInsetsMode != NEW_INSETS_MODE_FULL) { @@ -2305,6 +2345,11 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mForceReportNewAttributes = false; params = lp; } + if (sNewInsetsMode == NEW_INSETS_MODE_FULL) { + adjustLayoutParamsForCompatibility(lp); + controlInsetsForCompatibility(lp); + handleDispatchSystemUiVisibilityChanged(mCompatibleVisibilityInfo); + } if (mFirst || mAttachInfo.mViewVisibilityChanged) { mAttachInfo.mViewVisibilityChanged = false; @@ -2398,8 +2443,6 @@ public final class ViewRootImpl implements ViewParent, && !PixelFormat.formatHasAlpha(params.format)) { params.format = PixelFormat.TRANSLUCENT; } - adjustLayoutParamsForCompatibility(params); - controlInsetsForCompatibility(params); } if (mFirst || windowShouldResize || insetsChanged || @@ -7098,7 +7141,7 @@ public final class ViewRootImpl implements ViewParent, } public void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) { - if (mSeq != args.seq) { + if (mSeq != args.seq && sNewInsetsMode != NEW_INSETS_MODE_FULL) { // The sequence has changed, so we need to update our value and make // sure to do a traversal afterward so the window manager is given our // most recent data. @@ -7109,6 +7152,7 @@ public final class ViewRootImpl implements ViewParent, if (mView == null) return; if (args.localChanges != 0) { mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges); + args.localChanges = 0; } int visibility = args.globalVisibility&View.SYSTEM_UI_CLEARABLE_FLAGS; diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index fa61a0a0250b..f2852fa49b5e 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -21,10 +21,14 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowInsets.Type.systemBars; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -39,6 +43,8 @@ import android.view.SurfaceControl.Transaction; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; import android.view.test.InsetsModeSession; +import androidx.test.runner.AndroidJUnit4; + import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -50,8 +56,6 @@ import org.mockito.MockitoAnnotations; import java.util.List; -import androidx.test.runner.AndroidJUnit4; - /** * Tests for {@link InsetsAnimationControlImpl}. * @@ -90,6 +94,8 @@ public class InsetsAnimationControlImplTest { @Before public void setup() { MockitoAnnotations.initMocks(this); + doNothing().when(mMockController).updateCompatSysUiVisibility( + anyInt(), anyBoolean(), anyBoolean()); mTopLeash = new SurfaceControl.Builder(mSession) .setName("testSurface") .build(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f93309a84466..32802eed94f4 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -218,6 +218,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.View; +import android.view.ViewRootImpl; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManagerPolicyConstants.PointerEventListener; @@ -3689,7 +3690,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo w.mSeq++; w.mSystemUiVisibility = newValue; } - if (newValue != curValue || w.mAttrs.hasSystemUiListeners) { + if ((newValue != curValue || w.mAttrs.hasSystemUiListeners) + && ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq, visibility, newValue, diff); } |