Make the requested visibility always up-to-date
The new logic sends the requested visibility to server even when the
client doesn't have a control. This makes the requested visibility
reliable at the server side.
This CL also changes getRequestedState to getRequestedVisibility in
WindowState, because the frames in getRequestedState are not reliable.
Fix: 161247175
Fix: 166819574
Test: atest DisplayPolicyLayoutTests DisplayPolicyTests InsetsPolicyTest
InsetsSourceProviderTest InsetsStateControllerTest
WindowStateTests InsetsAnimationControlImplTest
InsetsControllerTest WindowAddRemovePerfTest
ActivityRecordTests
Change-Id: I7d32dacaa1302bab61386f5bd69aaa7dde953ebe
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index b11d7464..6f0001d 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -84,6 +84,7 @@
private static class TestWindow extends BaseIWindow {
final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
+ final InsetsState mRequestedVisibility = new InsetsState();
final Rect mOutFrame = new Rect();
final Rect mOutContentInsets = new Rect();
final Rect mOutStableInsets = new Rect();
@@ -108,7 +109,8 @@
long startTime = SystemClock.elapsedRealtimeNanos();
session.addToDisplay(this, mLayoutParams, View.VISIBLE,
- Display.DEFAULT_DISPLAY, mOutFrame, mOutContentInsets, mOutStableInsets,
+ Display.DEFAULT_DISPLAY, mRequestedVisibility, mOutFrame,
+ mOutContentInsets, mOutStableInsets,
mOutDisplayCutout, inputChannel, mOutInsetsState, mOutControls);
final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
state.addExtraResult("add", elapsedTimeNsOfAdd);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4d1337b..6a70a85 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -877,9 +877,10 @@
InputChannel inputChannel = new InputChannel();
if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE,
- mDisplay.getDisplayId(), mWinFrames.frame, mWinFrames.contentInsets,
- mWinFrames.stableInsets, mWinFrames.displayCutout, inputChannel,
- mInsetsState, mTempControls) < 0) {
+ mDisplay.getDisplayId(), mInsetsState, mWinFrames.frame,
+ mWinFrames.contentInsets, mWinFrames.stableInsets,
+ mWinFrames.displayCutout, inputChannel, mInsetsState,
+ mTempControls) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 910fd90..7f36169 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -45,12 +45,13 @@
*/
interface IWindowSession {
int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs,
- in int viewVisibility, in int layerStackId, out Rect outFrame,
- out Rect outContentInsets, out Rect outStableInsets,
+ in int viewVisibility, in int layerStackId, in InsetsState requestedVisibility,
+ out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, in int userId,
+ in InsetsState requestedVisibility,
out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 71899fa..878583b 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -212,21 +212,21 @@
/**
* @return Whether the finish callback of this animation should be invoked.
*/
- public boolean applyChangeInsets(InsetsState state) {
+ public boolean applyChangeInsets(@Nullable InsetsState outState) {
if (mCancelled) {
if (DEBUG) Log.d(TAG, "applyChangeInsets canceled");
return false;
}
final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
ArrayList<SurfaceParams> params = new ArrayList<>();
- updateLeashesForSide(ISIDE_LEFT, offset.left, mShownInsets.left, mPendingInsets.left,
- params, state, mPendingAlpha);
- updateLeashesForSide(ISIDE_TOP, offset.top, mShownInsets.top, mPendingInsets.top, params,
- state, mPendingAlpha);
- updateLeashesForSide(ISIDE_RIGHT, offset.right, mShownInsets.right, mPendingInsets.right,
- params, state, mPendingAlpha);
- updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mShownInsets.bottom,
- mPendingInsets.bottom, params, state, mPendingAlpha);
+ updateLeashesForSide(ISIDE_LEFT, offset.left, mPendingInsets.left, params, outState,
+ mPendingAlpha);
+ updateLeashesForSide(ISIDE_TOP, offset.top, mPendingInsets.top, params, outState,
+ mPendingAlpha);
+ updateLeashesForSide(ISIDE_RIGHT, offset.right, mPendingInsets.right, params, outState,
+ mPendingAlpha);
+ updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params, outState,
+ mPendingAlpha);
mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
mCurrentInsets = mPendingInsets;
@@ -357,8 +357,8 @@
return alpha >= 1 ? 1 : (alpha <= 0 ? 0 : alpha);
}
- private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int maxInset,
- int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
+ private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
+ ArrayList<SurfaceParams> surfaceParams, @Nullable InsetsState outState, float alpha) {
ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
if (items == null) {
return;
@@ -377,8 +377,10 @@
? (mAnimationType == ANIMATION_TYPE_SHOW ? true : !mFinished)
: inset != 0;
- state.getSource(source.getType()).setVisible(visible);
- state.getSource(source.getType()).setFrame(mTmpFrame);
+ if (outState != null) {
+ outState.getSource(source.getType()).setVisible(visible);
+ outState.getSource(source.getType()).setFrame(mTmpFrame);
+ }
// If the system is controlling the insets source, the leash can be null.
if (leash != null) {
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index cc3cd27..1307052 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -44,7 +44,6 @@
private final InsetsAnimationControlImpl mControl;
private final InsetsAnimationControlCallbacks mOuterCallbacks;
private final Handler mMainThreadHandler;
- private final InsetsState mState = new InsetsState();
private final InsetsAnimationControlCallbacks mCallbacks =
new InsetsAnimationControlCallbacks() {
@@ -60,7 +59,7 @@
@Override
public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
- mControl.applyChangeInsets(mState);
+ mControl.applyChangeInsets(null /* outState */);
}
@Override
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 652781a..5037d9e 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -484,7 +484,9 @@
/** The state dispatched from server */
private final InsetsState mLastDispatchedState = new InsetsState();
- /** The state sent to server */
+ // TODO: Use other class to represent the requested visibility of each type, because the
+ // display frame and the frame in each source are not used.
+ /** The requested visibilities sent to server */
private final InsetsState mRequestedState = new InsetsState();
private final Rect mFrame = new Rect();
@@ -499,6 +501,7 @@
private final List<WindowInsetsAnimation> mUnmodifiableTmpRunningAnims =
Collections.unmodifiableList(mTmpRunningAnims);
private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
+ private final ArraySet<InsetsSourceConsumer> mRequestedVisibilityChanged = new ArraySet<>();
private WindowInsets mLastInsets;
private boolean mAnimCallbackScheduled;
@@ -640,11 +643,6 @@
if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
mHost.notifyInsetsChanged();
}
- if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */,
- true /* excludeInvisibleIme */)) {
- if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState);
- updateRequestedState();
- }
return true;
}
@@ -808,9 +806,9 @@
if (hideTypes[0] != 0) {
applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
}
- if (requestedStateStale) {
- updateRequestedState();
- }
+
+ // InsetsSourceConsumer#setControl might change the requested visibility.
+ updateRequestedVisibility();
}
@Override
@@ -945,6 +943,7 @@
if (types == 0) {
// nothing to animate.
listener.onCancelled(null);
+ updateRequestedVisibility();
if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked");
return;
}
@@ -980,12 +979,14 @@
}
});
}
+ updateRequestedVisibility();
return;
}
if (typesReady == 0) {
if (DEBUG) Log.d(TAG, "No types ready. onCancelled()");
listener.onCancelled(null);
+ updateRequestedVisibility();
return;
}
@@ -1010,6 +1011,7 @@
} else {
hideDirectly(types, false /* animationFinished */, animationType);
}
+ updateRequestedVisibility();
}
/**
@@ -1177,7 +1179,6 @@
}
if (stateChanged) {
mHost.notifyInsetsChanged();
- updateRequestedState();
}
}
@@ -1202,7 +1203,6 @@
@VisibleForTesting
public void notifyVisibilityChanged() {
mHost.notifyInsetsChanged();
- updateRequestedState();
}
/**
@@ -1251,38 +1251,39 @@
return ANIMATION_TYPE_NONE;
}
+ @VisibleForTesting
+ public void onRequestedVisibilityChanged(InsetsSourceConsumer consumer) {
+ mRequestedVisibilityChanged.add(consumer);
+ }
+
/**
- * Sends the local visibility state back to window manager if it is changed.
+ * Sends the requested visibilities to window manager if any of them is changed.
*/
- private void updateRequestedState() {
+ private void updateRequestedVisibility() {
boolean changed = false;
- for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
- final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ for (int i = mRequestedVisibilityChanged.size() - 1; i >= 0; i--) {
+ final InsetsSourceConsumer consumer = mRequestedVisibilityChanged.valueAt(i);
final @InternalInsetsType int type = consumer.getType();
if (type == ITYPE_CAPTION_BAR) {
continue;
}
- if (consumer.getControl() != null) {
- final InsetsSource localSource = mState.getSource(type);
- if (!localSource.equals(mRequestedState.peekSource(type))) {
- // Our requested state is stale. Update it here and send it to window manager.
- mRequestedState.addSource(new InsetsSource(localSource));
- changed = true;
- }
- if (!localSource.equals(mLastDispatchedState.peekSource(type))) {
- // The server state is not what we expected. This can happen while we don't have
- // the control. Since we have the control now, we need to send our request again
- // to modify the server state.
- changed = true;
- }
+ final boolean requestedVisible = consumer.isRequestedVisible();
+ if (requestedVisible != mRequestedState.getSourceOrDefaultVisibility(type)) {
+ mRequestedState.getSource(type).setVisible(requestedVisible);
+ changed = true;
}
}
+ mRequestedVisibilityChanged.clear();
if (!changed) {
return;
}
mHost.onInsetsModified(mRequestedState);
}
+ InsetsState getRequestedVisibility() {
+ return mRequestedState;
+ }
+
@VisibleForTesting
public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) {
if (types == 0) {
@@ -1316,6 +1317,7 @@
for (int i = internalTypes.size() - 1; i >= 0; i--) {
getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType);
}
+ updateRequestedVisibility();
}
private void showDirectly(@InsetsType int types) {
@@ -1326,6 +1328,7 @@
for (int i = internalTypes.size() - 1; i >= 0; i--) {
getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */);
}
+ updateRequestedVisibility();
}
/**
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index d7ceaf7..e4a24eb 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -350,6 +350,7 @@
if (mRequestedVisible != requestedVisible) {
mRequestedVisible = requestedVisible;
mIsAnimationPending = false;
+ mController.onRequestedVisibilityChanged(this);
if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
}
if (applyLocalVisibilityOverride()) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 38441d1..b9f1f6a 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -63,8 +63,6 @@
*/
public class InsetsState implements Parcelable {
- public static final InsetsState EMPTY = new InsetsState();
-
/**
* Internal representation of inset source types. This is different from the public API in
* {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5235740..d2607c9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1021,8 +1021,10 @@
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
adjustLayoutParamsForCompatibility(mWindowAttributes);
+ controlInsetsForCompatibility(mWindowAttributes);
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrames.frame,
+ getHostVisibility(), mDisplay.getDisplayId(), userId,
+ mInsetsController.getRequestedVisibility(), mTmpFrames.frame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 90a80ce..8f58df4 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -144,7 +144,9 @@
@Override
public void onInsetsModified(InsetsState insetsState) {
try {
- mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+ if (mViewRoot.mAdded) {
+ mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+ }
} catch (RemoteException e) {
Log.e(TAG, "Failed to call insetsModified", e);
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 0c221ed..8147873 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -130,8 +130,8 @@
*/
@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
- Rect outStableInsets,
+ int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+ Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
@@ -166,11 +166,11 @@
*/
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, int userId, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
+ int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+ Rect outFrame, Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
- return addToDisplay(window, attrs, viewVisibility, displayId,
+ return addToDisplay(window, attrs, viewVisibility, displayId, requestedVisibility,
outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
outInsetsState, outActiveControls);
}
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 8412e53..b98ce30 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -27,6 +27,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -89,6 +90,7 @@
mInsetsState = new InsetsState();
mInsetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 500, 100));
mInsetsState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
+ doNothing().when(mMockController).onRequestedVisibilityChanged(any());
InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mInsetsState,
() -> mMockTransaction, mMockController);
topConsumer.setControl(
@@ -130,7 +132,7 @@
public void testChangeInsets() {
mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 1f /* alpha */,
0f /* fraction */);
- mController.applyChangeInsets(new InsetsState());
+ mController.applyChangeInsets(null /* outState */);
assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
assertEquals(1f, mController.getCurrentAlpha(), 1f - mController.getCurrentAlpha());
@@ -150,7 +152,7 @@
public void testChangeAlphaNoInsets() {
Insets initialInsets = mController.getCurrentInsets();
mController.setInsetsAndAlpha(null, 0.5f, 0f /* fraction*/);
- mController.applyChangeInsets(new InsetsState());
+ mController.applyChangeInsets(null /* outState */);
assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
assertEquals(initialInsets, mController.getCurrentInsets());
}
@@ -158,7 +160,7 @@
@Test
public void testChangeInsetsAndAlpha() {
mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 0.5f, 1f);
- mController.applyChangeInsets(new InsetsState());
+ mController.applyChangeInsets(null /* outState */);
assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index cc97eb5..7b84f68c 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -683,71 +683,15 @@
@Test
public void testRequestedState() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final InsetsState state = mTestHost.getRequestedState();
- // The modified state can be controlled when we have control.
- mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
- mController.hide(statusBars());
- assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
+ mController.hide(statusBars() | navigationBars());
+ assertFalse(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+ assertFalse(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
- // The modified state won't be changed while losing control.
- mController.onControlsChanged(null /* activeControls */);
- assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
- // The modified state won't be changed while state changed while we don't have control.
- InsetsState newState = new InsetsState(mController.getState(), true /* copySource */);
- mController.onStateChanged(newState);
- assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
- // The modified state won't be changed while controlling an insets without having the
- // control.
- mController.show(statusBars());
- assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
- // The modified state can be updated while gaining control.
- mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
- assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
- // The modified state can still be updated if the local state and the requested state
- // are the same.
- mController.onControlsChanged(null /* activeControls */);
- mController.hide(statusBars());
- newState = new InsetsState(mController.getState(), true /* copySource */);
- newState.getSource(ITYPE_STATUS_BAR).setVisible(false);
- mController.onStateChanged(newState);
- mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
- assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
- // The modified state will always be updated while receiving IME control if IME is
- // requested visible.
- mController.getSourceConsumer(ITYPE_IME).show(false /* fromIme */);
- newState = new InsetsState(mController.getState(), true /* copySource */);
- newState.getSource(ITYPE_IME).setVisible(true);
- newState.getSource(ITYPE_IME).setFrame(1, 2, 3, 4);
- mController.onStateChanged(newState);
- mController.onControlsChanged(createSingletonControl(ITYPE_IME));
- assertEquals(newState.getSource(ITYPE_IME),
- mTestHost.getModifiedState().peekSource(ITYPE_IME));
- newState = new InsetsState(mController.getState(), true /* copySource */);
- newState.getSource(ITYPE_IME).setVisible(true);
- newState.getSource(ITYPE_IME).setFrame(5, 6, 7, 8);
- mController.onStateChanged(newState);
- mController.onControlsChanged(createSingletonControl(ITYPE_IME));
- assertEquals(newState.getSource(ITYPE_IME),
- mTestHost.getModifiedState().peekSource(ITYPE_IME));
-
- // The modified frames cannot be updated if there is an animation.
- mController.onControlsChanged(createSingletonControl(ITYPE_NAVIGATION_BAR));
- mController.hide(navigationBars());
- newState = new InsetsState(mController.getState(), true /* copySource */);
- newState.getSource(ITYPE_NAVIGATION_BAR).getFrame().top--;
- mController.onStateChanged(newState);
- assertNotEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
- mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
-
- // The modified frames can be updated while the animation is done.
- mController.cancelExistingAnimations();
- assertEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
- mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
+ mController.show(statusBars() | navigationBars());
+ assertTrue(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+ assertTrue(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
});
}
@@ -878,7 +822,7 @@
public static class TestHost extends ViewRootInsetsControllerHost {
- private InsetsState mModifiedState = new InsetsState();
+ private final InsetsState mRequestedState = new InsetsState();
TestHost(ViewRootImpl viewRoot) {
super(viewRoot);
@@ -886,12 +830,12 @@
@Override
public void onInsetsModified(InsetsState insetsState) {
- mModifiedState = new InsetsState(insetsState, true /* copySource */);
+ mRequestedState.set(insetsState, true);
super.onInsetsModified(insetsState);
}
- public InsetsState getModifiedState() {
- return mModifiedState;
+ public InsetsState getRequestedState() {
+ return mRequestedState;
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index be03e91..0291611 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -192,6 +192,8 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputWindowHandle;
+import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationDefinition;
@@ -4826,7 +4828,7 @@
boolean ignoreRequest) {
final int type = win.mAttrs.type;
final boolean stickyHideNav =
- !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
&& win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
&& type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
@@ -5553,6 +5555,7 @@
class RemoteInsetsControlTarget implements InsetsControlTarget {
private final IDisplayWindowInsetsController mRemoteInsetsController;
+ private final InsetsState mRequestedInsetsState = new InsetsState();
RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) {
mRemoteInsetsController = controller;
@@ -5608,6 +5611,19 @@
Slog.w(TAG, "Failed to deliver showInsets", e);
}
}
+
+ @Override
+ public boolean getRequestedVisibility(@InternalInsetsType int type) {
+ return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
+ }
+
+ void updateRequestedVisibility(InsetsState state) {
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ final InsetsSource source = state.peekSource(i);
+ if (source == null) continue;
+ mRequestedInsetsState.addSource(source);
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4e7e0ba..b2cf856 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1659,10 +1659,8 @@
provider != null ? provider.getControlTarget() : null;
final WindowState navControllingWin =
navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null;
- final InsetsState requestedState = navControllingWin != null
- ? navControllingWin.getRequestedInsetsState() : null;
- final boolean navVisible = requestedState != null
- ? requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ final boolean navVisible = navControllingWin != null
+ ? navControllingWin.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
: InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
final boolean showBarsByTouch = navControllingWin != null
&& navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH;
@@ -2073,11 +2071,10 @@
// the cutout safe zone.
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
final boolean attachedInParent = attached != null && !layoutInScreen;
- final InsetsState requestedInsetsState = win.getRequestedInsetsState();
final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
- || !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR);
+ || !win.getRequestedVisibility(ITYPE_STATUS_BAR);
final boolean requestedHideNavigation =
- !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+ !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
// TYPE_BASE_APPLICATION windows are never considered floating here because they don't
// get cropped / shifted to the displayFrame in WindowState.
@@ -2423,14 +2420,8 @@
}
final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
final int fl = attrs.flags;
- final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
- .peekSource(ITYPE_STATUS_BAR);
- if (WindowManagerDebugConfig.DEBUG) {
- Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrame());
- Slog.d(TAG, "attr: " + attrs + " request: " + request);
- }
return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
- || (request != null && !request.isVisible());
+ || !mTopFullscreenOpaqueWindowState.getRequestedVisibility(ITYPE_STATUS_BAR);
}
/**
@@ -2864,18 +2855,15 @@
return;
}
- final InsetsState requestedState = controlTarget.getRequestedInsetsState();
final @InsetsType int restorePositionTypes =
- (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ (controlTarget.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
? Type.navigationBars() : 0)
- | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
+ | (controlTarget.getRequestedVisibility(ITYPE_STATUS_BAR)
? Type.statusBars() : 0)
- | (mExtraNavBarAlt != null
- && requestedState.getSourceOrDefaultVisibility(
+ | (mExtraNavBarAlt != null && controlTarget.getRequestedVisibility(
ITYPE_EXTRA_NAVIGATION_BAR)
? Type.navigationBars() : 0)
- | (mClimateBarAlt != null
- && requestedState.getSourceOrDefaultVisibility(
+ | (mClimateBarAlt != null && controlTarget.getRequestedVisibility(
ITYPE_CLIMATE_BAR)
? Type.statusBars() : 0);
@@ -2981,12 +2969,11 @@
win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState,
mTopFullscreenOpaqueOrDimmingWindowState,
mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance;
- final InsetsState requestedInsets = win.getRequestedInsetsState();
final int behavior = win.mAttrs.insetsFlags.behavior;
final boolean isImmersive = behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
|| behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
- final boolean isFullscreen = !requestedInsets.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
- || !requestedInsets.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+ final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR)
+ || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
if (mLastDisableFlags == disableFlags
&& mLastAppearance == appearance
&& mLastFullscreenAppearance == fullscreenAppearance
@@ -3152,10 +3139,7 @@
freeformStackVisible, resizing, fullscreenDrawsNavBarBackground,
dockedDrawsNavigationBarBackground);
- final InsetsState requestedInsetsState = win.getRequestedInsetsState();
- final boolean requestHideNavBar = !requestedInsetsState.getSourceOrDefaultVisibility(
- ITYPE_NAVIGATION_BAR);
-
+ final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
final long now = SystemClock.uptimeMillis();
final boolean pendingPanic = mPendingPanicGestureUptime != 0
&& now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 5e7ed3f..287dd74 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -18,6 +18,7 @@
import android.inputmethodservice.InputMethodService;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
/**
@@ -39,10 +40,10 @@
}
/**
- * @return The requested {@link InsetsState} of this target.
+ * @return The requested visibility of this target.
*/
- default InsetsState getRequestedInsetsState() {
- return InsetsState.EMPTY;
+ default boolean getRequestedVisibility(@InternalInsetsType int type) {
+ return InsetsState.getDefaultVisibility(type);
}
/**
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3617884..bd05da9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -173,13 +173,7 @@
// animation frame which will be triggered if a new leash is created.
mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
- final InsetsState state = new InsetsState(mStateController.getRawInsetsState());
- startAnimation(true /* show */, () -> {
- synchronized (mDisplayContent.mWmService.mGlobalLock) {
- mStateController.notifyInsetsChanged();
- }
- }, state);
- mStateController.onInsetsModified(mDummyControlTarget, state);
+ startAnimation(true /* show */, null /* callback */);
}
});
}
@@ -189,15 +183,18 @@
if (mShowingTransientTypes.size() == 0) {
return;
}
- InsetsState state = new InsetsState(mStateController.getRawInsetsState());
startAnimation(false /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
+ for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ // We are about to clear mShowingTransientTypes, we don't want the transient bar
+ // can cause insets on the client. Restore the client visibility.
+ final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+ mStateController.getSourceProvider(type).setClientVisible(false);
+ }
mShowingTransientTypes.clear();
- mStateController.notifyInsetsChanged();
updateBarControlTarget(mFocusedWin);
}
- }, state);
- mStateController.onInsetsModified(mDummyControlTarget, state);
+ });
}
boolean isTransient(@InternalInsetsType int type) {
@@ -211,7 +208,7 @@
final InsetsState originalState = mStateController.getInsetsForDispatch(target);
InsetsState state = originalState;
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- final int type = mShowingTransientTypes.get(i);
+ final @InternalInsetsType int type = mShowingTransientTypes.get(i);
final InsetsSource originalSource = state.peekSource(type);
if (originalSource != null && originalSource.isVisible()) {
if (state == originalState) {
@@ -227,26 +224,25 @@
return state;
}
- void onInsetsModified(WindowState windowState, InsetsState state) {
- mStateController.onInsetsModified(windowState, state);
- checkAbortTransient(windowState, state);
+ void onInsetsModified(InsetsControlTarget caller) {
+ mStateController.onInsetsModified(caller);
+ checkAbortTransient(caller);
updateBarControlTarget(mFocusedWin);
}
/**
- * Called when a window modified the insets state. If the window set a insets source to visible
- * while it is shown transiently, we need to abort the transient state.
+ * Called when a control target modified the insets state. If the target set a insets source to
+ * visible while it is shown transiently, we need to abort the transient state.
*
- * @param windowState who changed the insets state.
- * @param state the modified insets state.
+ * @param caller who changed the insets state.
*/
- private void checkAbortTransient(WindowState windowState, InsetsState state) {
+ private void checkAbortTransient(InsetsControlTarget caller) {
if (mShowingTransientTypes.size() != 0) {
IntArray abortTypes = new IntArray();
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- final int type = mShowingTransientTypes.get(i);
- if (mStateController.isFakeTarget(type, windowState)
- && state.getSource(type).isVisible()) {
+ final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+ if (mStateController.isFakeTarget(type, caller)
+ && caller.getRequestedVisibility(type)) {
mShowingTransientTypes.remove(i);
abortTypes.add(type);
}
@@ -393,12 +389,12 @@
}
@VisibleForTesting
- void startAnimation(boolean show, Runnable callback, InsetsState state) {
+ void startAnimation(boolean show, Runnable callback) {
int typesReady = 0;
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
final IntArray showingTransientTypes = mShowingTransientTypes;
for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
- int type = showingTransientTypes.get(i);
+ final @InternalInsetsType int type = showingTransientTypes.get(i);
InsetsSourceProvider provider = mStateController.getSourceProvider(type);
InsetsSourceControl control = provider.getControl(mDummyControlTarget);
if (control == null || control.getLeash() == null) {
@@ -406,7 +402,6 @@
}
typesReady |= InsetsState.toPublicType(type);
controls.put(control.getType(), new InsetsSourceControl(control));
- state.setSourceVisible(type, show);
}
controlAnimationUnchecked(typesReady, controls, show, callback);
}
@@ -428,12 +423,9 @@
mId = id;
}
- private void updateVisibility(InsetsControlTarget controlTarget,
+ private void updateVisibility(@Nullable InsetsControlTarget controlTarget,
@InternalInsetsType int type) {
- final WindowState controllingWin =
- controlTarget instanceof WindowState ? (WindowState) controlTarget : null;
- setVisible(controllingWin == null
- || controllingWin.getRequestedInsetsState().getSourceOrDefaultVisibility(type));
+ setVisible(controlTarget == null || controlTarget.getRequestedVisibility(type));
}
private void setVisible(boolean visible) {
@@ -463,7 +455,9 @@
@Override
protected void onAnimationFinish() {
super.onAnimationFinish();
- DisplayThread.getHandler().post(mFinishCallback);
+ if (mFinishCallback != null) {
+ DisplayThread.getHandler().post(mFinishCallback);
+ }
}
private class InsetsPolicyAnimationControlCallbacks implements
@@ -484,7 +478,7 @@
mAnimatingShown = show;
mAnimationControl = new InsetsAnimationControlImpl(controls,
- mFocusedWin.getDisplayContent().getBounds(), getState(),
+ mFocusedWin.getDisplayContent().getBounds(), mFocusedWin.getInsetsState(),
mListener, typesReady, this, mListener.getDurationMs(),
InsetsController.SYSTEM_BARS_INTERPOLATOR,
show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
@@ -495,8 +489,7 @@
/** Called on SurfaceAnimationThread without global WM lock held. */
@Override
public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
- InsetsState state = getState();
- if (mAnimationControl.applyChangeInsets(state)) {
+ if (mAnimationControl.applyChangeInsets(null /* outState */)) {
mAnimationControl.finish(mAnimatingShown);
}
}
@@ -507,20 +500,6 @@
// onAnimationFinished callback.
}
- /**
- * This method will return a state with fullscreen frame override. No need to make copy
- * after getting state from this method.
- * @return The client insets state with full display frame override.
- */
- private InsetsState getState() {
- // To animate the transient animation correctly, we need to let the state hold
- // the full display frame.
- InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(),
- true);
- overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds());
- return overrideState;
- }
-
/** Called on SurfaceAnimationThread without global WM lock held. */
@Override
public void applySurfaceParams(
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 7defc5d..e83151d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -338,11 +338,12 @@
}
}
- boolean onInsetsModified(InsetsControlTarget caller, InsetsSource modifiedSource) {
- if (mControlTarget != caller || modifiedSource.isVisible() == mClientVisible) {
+ boolean updateClientVisibility(InsetsControlTarget caller) {
+ final boolean requestedVisible = caller.getRequestedVisibility(mSource.getType());
+ if (caller != mControlTarget || requestedVisible == mClientVisible) {
return false;
}
- setClientVisible(modifiedSource.isVisible());
+ setClientVisible(requestedVisible);
return true;
}
@@ -350,7 +351,7 @@
mIsLeashReadyForDispatching = true;
}
- private void setClientVisible(boolean clientVisible) {
+ void setClientVisible(boolean clientVisible) {
if (mClientVisible == clientVisible) {
return;
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b59452f..b9c2093 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -289,16 +289,10 @@
winInsetsChanged.clear();
}
- void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
+ void onInsetsModified(InsetsControlTarget caller) {
boolean changed = false;
- for (int i = 0; i < InsetsState.SIZE; i++) {
- final InsetsSource source = state.peekSource(i);
- if (source == null) continue;
- final InsetsSourceProvider provider = mProviders.get(source.getType());
- if (provider == null) {
- continue;
- }
- changed |= provider.onInsetsModified(windowState, source);
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ changed |= mProviders.valueAt(i).updateClientVisibility(caller);
}
if (changed) {
notifyInsetsChanged();
@@ -464,11 +458,24 @@
final InsetsSourceProvider provider = mProviders.valueAt(i);
provider.onSurfaceTransactionApplied();
}
+ final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
controlTarget.notifyInsetsControlChanged();
+ if (mControlTargetTypeMap.containsKey(controlTarget)) {
+ // We only collect targets who get controls, not lose controls.
+ newControlTargets.add(controlTarget);
+ }
}
mPendingControlChanged.clear();
+
+ // This updates the insets visibilities AFTER sending current insets state and controls
+ // to the clients, so that the clients can change the current visibilities to the
+ // requested visibilities with animations.
+ for (int i = newControlTargets.size() - 1; i >= 0; i--) {
+ onInsetsModified(newControlTargets.valueAt(i));
+ }
+ newControlTargets.clear();
});
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 02230d6..f84e70e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -92,6 +92,7 @@
private float mLastReportedAnimatorScale;
private String mPackageName;
private String mRelayoutTag;
+ private final InsetsState mDummyRequestedVisibility = new InsetsState();
private final InsetsSourceControl[] mDummyControls = new InsetsSourceControl[0];
public Session(WindowManagerService service, IWindowSessionCallback callback) {
@@ -158,25 +159,26 @@
@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
- Rect outStableInsets,
+ int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+ Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
- return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
+ return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+ UserHandle.getUserId(mUid), requestedVisibility, outFrame,
outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
- outInsetsState, outActiveControls, UserHandle.getUserId(mUid));
+ outInsetsState, outActiveControls);
}
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, int userId, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
+ int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+ Rect outFrame, Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
- return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
- outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
- outInsetsState, outActiveControls, userId);
+ return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
+ requestedVisibility, outFrame, outContentInsets, outStableInsets, outDisplayCutout,
+ outInputChannel, outInsetsState, outActiveControls);
}
@Override
@@ -184,9 +186,10 @@
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
InsetsState outInsetsState) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+ UserHandle.getUserId(mUid), mDummyRequestedVisibility,
new Rect() /* outFrame */, outContentInsets, outStableInsets,
new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
- outInsetsState, mDummyControls, UserHandle.getUserId(mUid));
+ outInsetsState, mDummyControls);
}
@Override
@@ -493,9 +496,8 @@
final WindowState windowState = mService.windowForClientLocked(this, window,
false /* throwOnError */);
if (windowState != null) {
- windowState.updateRequestedInsetsState(state);
- windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
- windowState, state);
+ windowState.updateRequestedVisibility(state);
+ windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(windowState);
}
}
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 87b470a..01adb8b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -482,8 +482,7 @@
final int color = ColorUtils.setAlphaComponent(
task.getTaskDescription().getBackgroundColor(), 255);
final LayoutParams attrs = mainWindow.getAttrs();
- final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState());
- mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState());
+ final InsetsState insetsState = getInsetsStateWithVisibilityOverride(mainWindow);
final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
@@ -603,13 +602,18 @@
return 0;
}
- static void mergeInsetsSources(InsetsState base, InsetsState other) {
+ static InsetsState getInsetsStateWithVisibilityOverride(WindowState win) {
+ final InsetsState state = new InsetsState(win.getInsetsState());
for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
- final InsetsSource source = other.peekSource(type);
- if (source != null) {
- base.addSource(source);
+ final boolean requestedVisible = win.getRequestedVisibility(type);
+ InsetsSource source = state.peekSource(type);
+ if (source != null && source.isVisible() != requestedVisible) {
+ source = new InsetsSource(source);
+ source.setVisible(requestedVisible);
+ state.addSource(source);
}
}
+ return state;
}
static Rect getSystemBarInsets(Rect frame, InsetsState state) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index efa0525..e8c4491 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -42,8 +42,8 @@
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.TaskSnapshotController.getInsetsStateWithVisibilityOverride;
import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
-import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -236,14 +236,15 @@
task.getBounds(taskBounds);
currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
activityType = activity.getActivityType();
- insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState());
- mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState());
+ insetsState = getInsetsStateWithVisibilityOverride(topFullscreenOpaqueWindow);
+
}
try {
final int res = session.addToDisplay(window, layoutParams,
- View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrames.frame,
- tmpFrames.contentInsets, tmpFrames.stableInsets, tmpFrames.displayCutout,
- null /* outInputChannel */, mTmpInsetsState, mTempControls);
+ View.GONE, activity.getDisplayContent().getDisplayId(), mTmpInsetsState,
+ tmpFrames.frame, tmpFrames.contentInsets, tmpFrames.stableInsets,
+ tmpFrames.displayCutout, null /* outInputChannel */, mTmpInsetsState,
+ mTempControls);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
return null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4be118e..faa5de1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1377,10 +1377,10 @@
}
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
- int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
+ int displayId, int requestUserId, InsetsState requestedVisibility, Rect outFrame,
+ Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
- InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
- int requestUserId) {
+ InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
Arrays.fill(outActiveControls, null);
int[] appOp = new int[1];
final boolean isRoundedCornerOverlay = (attrs.privateFlags
@@ -1575,6 +1575,7 @@
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid);
+ win.updateRequestedVisibility(requestedVisibility);
res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -4014,8 +4015,8 @@
if (dc == null || dc.mRemoteInsetsControlTarget == null) {
return;
}
- dc.getInsetsStateController().onInsetsModified(
- dc.mRemoteInsetsControlTarget, state);
+ dc.mRemoteInsetsControlTarget.updateRequestedVisibility(state);
+ dc.getInsetsStateController().onInsetsModified(dc.mRemoteInsetsControlTarget);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 25b4828..90c3d6c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -224,6 +224,7 @@
import android.view.InputWindowHandle;
import android.view.InsetsSource;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -719,20 +720,20 @@
private final WindowProcessController mWpcForDisplayConfigChanges;
/**
- * @return The insets state as requested by the client, i.e. the dispatched insets state
- * for which the visibilities are overridden with what the client requested.
+ * Returns the visibility of the given {@link InternalInsetsType type} requested by the client.
+ *
+ * @param type the given {@link InternalInsetsType type}.
+ * @return {@code true} if the type is requested visible.
*/
@Override
- public InsetsState getRequestedInsetsState() {
- return mRequestedInsetsState;
+ public boolean getRequestedVisibility(@InternalInsetsType int type) {
+ return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
}
/**
- * @see #getRequestedInsetsState()
+ * @see #getRequestedVisibility(int)
*/
- void updateRequestedInsetsState(InsetsState state) {
-
- // Only update the sources the client is actually controlling.
+ void updateRequestedVisibility(InsetsState state) {
for (int i = 0; i < InsetsState.SIZE; i++) {
final InsetsSource source = state.peekSource(i);
if (source == null) continue;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index dd85484..ad9692f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1523,7 +1523,8 @@
// Return error to skip unnecessary operation.
doReturn(WindowManagerGlobal.ADD_STARTING_NOT_NEEDED).when(session).addToDisplay(
any() /* window */, any() /* attrs */,
- anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* outFrame */,
+ anyInt() /* viewVisibility */, anyInt() /* displayId */,
+ any() /* requestedVisibility */, any() /* outFrame */,
any() /* outContentInsets */, any() /* outStableInsets */,
any() /* outDisplayCutout */, any() /* outInputChannel */,
any() /* outInsetsState */, any() /* outActiveControls */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2920c1d..5a14a24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -522,7 +522,9 @@
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
- mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+ final InsetsState requestedState = new InsetsState();
+ requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ mWindow.updateRequestedVisibility(requestedState);
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -544,7 +546,9 @@
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
- mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+ final InsetsState requestedState = new InsetsState();
+ requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ mWindow.updateRequestedVisibility(requestedState);
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
addWindow(mWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index a55423a..21bdc9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -313,8 +313,8 @@
// App requests to hide navigation bar.
final InsetsState requestedState = new InsetsState();
requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
- mAppWindow.updateRequestedInsetsState(requestedState);
- insetsPolicy.onInsetsModified(mAppWindow, requestedState);
+ mAppWindow.updateRequestedVisibility(requestedState);
+ insetsPolicy.onInsetsModified(mAppWindow);
assertNotNull(displayPolicy.mInputConsumer);
// App still requests to hide navigation bar, but without BEHAVIOR_SHOW_BARS_BY_TOUCH.
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c02faf..d67120f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -38,7 +38,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -180,7 +179,7 @@
final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
final InsetsState requestedState = new InsetsState();
requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
- fullscreenApp.updateRequestedInsetsState(requestedState);
+ fullscreenApp.updateRequestedVisibility(requestedState);
// Add a non-fullscreen dialog window.
final WindowState dialog = addWindow(TYPE_APPLICATION, "dialog");
@@ -215,7 +214,7 @@
final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp");
final InsetsState newRequestedState = new InsetsState();
newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState);
+ newFocusedFullscreenApp.updateRequestedVisibility(newRequestedState);
// Make sure status bar is hidden by previous insets state.
mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp);
@@ -232,20 +231,28 @@
@UseTestDisplay(addWindows = W_ACTIVITY)
@Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
- addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
- .getControllableInsetProvider().getSource().setVisible(false);
- addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
- .getControllableInsetProvider().getSource().setVisible(false);
+ final WindowState statusBar = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar");
+ statusBar.setHasSurface(true);
+ statusBar.getControllableInsetProvider().setServerVisible(true);
+ final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
+ navBar.setHasSurface(true);
+ navBar.getControllableInsetProvider().setServerVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
- doAnswer(invocation -> {
- ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_STATUS_BAR, true);
- ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_NAVIGATION_BAR, true);
- return null;
- }).when(policy).startAnimation(anyBoolean(), any(), any());
-
+ // Make both system bars invisible.
+ final InsetsState requestedState = new InsetsState();
+ requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+ mAppWindow.updateRequestedVisibility(requestedState);
policy.updateBarControlTarget(mAppWindow);
+ waitUntilWindowAnimatorIdle();
+ assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_STATUS_BAR).isVisible());
+ assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_NAVIGATION_BAR).isVisible());
+
policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
final InsetsSourceControl[] controls =
@@ -272,7 +279,7 @@
.getControllableInsetProvider().setServerVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(mAppWindow);
policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
@@ -301,7 +308,7 @@
.getControllableInsetProvider().getSource().setVisible(false);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(mAppWindow);
policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
@@ -326,7 +333,8 @@
assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible());
assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
- policy.onInsetsModified(mAppWindow, state);
+ mAppWindow.updateRequestedVisibility(state);
+ policy.onInsetsModified(mAppWindow);
waitUntilWindowAnimatorIdle();
controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -348,7 +356,7 @@
final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(app);
policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
final InsetsSourceControl[] controls =
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index a0fa936..9830631 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -205,7 +205,8 @@
mProvider.updateControlForTarget(target, false /* force */);
InsetsState state = new InsetsState();
state.getSource(ITYPE_STATUS_BAR).setVisible(false);
- mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+ target.updateRequestedVisibility(state);
+ mProvider.updateClientVisibility(target);
assertFalse(mSource.isVisible());
}
@@ -217,7 +218,8 @@
mProvider.setWindow(statusBar, null, null);
InsetsState state = new InsetsState();
state.getSource(ITYPE_STATUS_BAR).setVisible(false);
- mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+ target.updateRequestedVisibility(state);
+ mProvider.updateClientVisibility(target);
assertTrue(mSource.isVisible());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index e2cd8a9..c14df67 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -189,8 +189,8 @@
getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget);
final InsetsState requestedState = new InsetsState();
requestedState.getSource(ITYPE_IME).setVisible(true);
- mDisplayContent.mInputMethodInputTarget.updateRequestedInsetsState(requestedState);
- getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget, requestedState);
+ mDisplayContent.mInputMethodInputTarget.updateRequestedVisibility(requestedState);
+ getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget);
// Send our spy window (app) into the system so that we can detect the invocation.
final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index c18043f..19bed48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -71,7 +71,7 @@
import android.platform.test.annotations.Presubmit;
import android.util.Size;
import android.view.DisplayCutout;
-import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -426,10 +426,11 @@
.setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */);
mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
- final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
- source.setVisible(false);
+ final InsetsState state = new InsetsState();
+ state.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ app.updateRequestedVisibility(state);
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
- .onInsetsModified(app, source);
+ .updateClientVisibility(app);
waitUntilHandlersIdle();
assertFalse(statusBar.isVisible());
}