Merge "Ensure the requested insets state is up to date" into rvc-dev
This commit is contained in:
@@ -22,8 +22,6 @@ import static android.view.InsetsState.toInternalType;
|
|||||||
import static android.view.InsetsState.toPublicType;
|
import static android.view.InsetsState.toPublicType;
|
||||||
import static android.view.WindowInsets.Type.all;
|
import static android.view.WindowInsets.Type.all;
|
||||||
import static android.view.WindowInsets.Type.ime;
|
import static android.view.WindowInsets.Type.ime;
|
||||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
|
|
||||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
|
|
||||||
|
|
||||||
import android.animation.AnimationHandler;
|
import android.animation.AnimationHandler;
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
@@ -43,7 +41,6 @@ import android.util.SparseArray;
|
|||||||
import android.view.InsetsSourceConsumer.ShowResult;
|
import android.view.InsetsSourceConsumer.ShowResult;
|
||||||
import android.view.InsetsState.InternalInsetsType;
|
import android.view.InsetsState.InternalInsetsType;
|
||||||
import android.view.SurfaceControl.Transaction;
|
import android.view.SurfaceControl.Transaction;
|
||||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
|
||||||
import android.view.WindowInsets.Type;
|
import android.view.WindowInsets.Type;
|
||||||
import android.view.WindowInsets.Type.InsetsType;
|
import android.view.WindowInsets.Type.InsetsType;
|
||||||
import android.view.WindowInsetsAnimation.Bounds;
|
import android.view.WindowInsetsAnimation.Bounds;
|
||||||
@@ -424,8 +421,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
|
|
||||||
private final String TAG = "InsetsControllerImpl";
|
private final String TAG = "InsetsControllerImpl";
|
||||||
|
|
||||||
|
/** The local state */
|
||||||
private final InsetsState mState = new InsetsState();
|
private final InsetsState mState = new InsetsState();
|
||||||
private final InsetsState mLastDispachedState = new InsetsState();
|
|
||||||
|
/** The state dispatched from server */
|
||||||
|
private final InsetsState mLastDispatchedState = new InsetsState();
|
||||||
|
|
||||||
|
/** The state sent to server */
|
||||||
|
private final InsetsState mRequestedState = new InsetsState();
|
||||||
|
|
||||||
private final Rect mFrame = new Rect();
|
private final Rect mFrame = new Rect();
|
||||||
private final BiFunction<InsetsController, Integer, InsetsSourceConsumer> mConsumerCreator;
|
private final BiFunction<InsetsController, Integer, InsetsSourceConsumer> mConsumerCreator;
|
||||||
@@ -539,24 +542,24 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
}
|
}
|
||||||
|
|
||||||
public InsetsState getLastDispatchedState() {
|
public InsetsState getLastDispatchedState() {
|
||||||
return mLastDispachedState;
|
return mLastDispatchedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public boolean onStateChanged(InsetsState state) {
|
public boolean onStateChanged(InsetsState state) {
|
||||||
boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
|
boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
|
||||||
|| !captionInsetsUnchanged();
|
|| !captionInsetsUnchanged();
|
||||||
if (!localStateChanged && mLastDispachedState.equals(state)) {
|
if (!localStateChanged && mLastDispatchedState.equals(state)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
updateState(state);
|
updateState(state);
|
||||||
mLastDispachedState.set(state, true /* copySources */);
|
mLastDispatchedState.set(state, true /* copySources */);
|
||||||
applyLocalVisibilityOverride();
|
applyLocalVisibilityOverride();
|
||||||
if (localStateChanged) {
|
if (localStateChanged) {
|
||||||
mHost.notifyInsetsChanged();
|
mHost.notifyInsetsChanged();
|
||||||
}
|
}
|
||||||
if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
|
if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */)) {
|
||||||
sendStateToWindowManager();
|
updateRequestedState();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -629,8 +632,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] showTypes = new int[1];
|
final boolean hasControl = mTmpControlArray.size() > 0;
|
||||||
int[] hideTypes = new int[1];
|
final int[] showTypes = new int[1];
|
||||||
|
final int[] hideTypes = new int[1];
|
||||||
|
|
||||||
// Ensure to update all existing source consumers
|
// Ensure to update all existing source consumers
|
||||||
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
||||||
@@ -663,6 +667,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
if (hideTypes[0] != 0) {
|
if (hideTypes[0] != 0) {
|
||||||
applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
|
applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
|
||||||
}
|
}
|
||||||
|
if (hasControl) {
|
||||||
|
// We might have changed our requested visibilities while we don't have the control,
|
||||||
|
// so we need to update our requested state once we have control. Otherwise, our
|
||||||
|
// requested state at the server side might be incorrect.
|
||||||
|
updateRequestedState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -992,7 +1002,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void notifyVisibilityChanged() {
|
public void notifyVisibilityChanged() {
|
||||||
mHost.notifyInsetsChanged();
|
mHost.notifyInsetsChanged();
|
||||||
sendStateToWindowManager();
|
updateRequestedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1042,18 +1052,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the local visibility state back to window manager.
|
* Sends the local visibility state back to window manager if it is changed.
|
||||||
*/
|
*/
|
||||||
private void sendStateToWindowManager() {
|
private void updateRequestedState() {
|
||||||
InsetsState tmpState = new InsetsState();
|
boolean changed = false;
|
||||||
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
||||||
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
|
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
|
||||||
if (consumer.getType() == ITYPE_CAPTION_BAR) continue;
|
final @InternalInsetsType int type = consumer.getType();
|
||||||
|
if (type == ITYPE_CAPTION_BAR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (consumer.getControl() != null) {
|
if (consumer.getControl() != null) {
|
||||||
tmpState.addSource(mState.getSource(consumer.getType()));
|
final InsetsSource localSource = mState.getSource(type);
|
||||||
|
if (!localSource.equals(mRequestedState.peekSource(type))) {
|
||||||
|
mRequestedState.addSource(new InsetsSource(localSource));
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mHost.onInsetsModified(tmpState);
|
}
|
||||||
|
if (!changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mHost.onInsetsModified(mRequestedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ public class InsetsControllerTest {
|
|||||||
private SurfaceSession mSession = new SurfaceSession();
|
private SurfaceSession mSession = new SurfaceSession();
|
||||||
private SurfaceControl mLeash;
|
private SurfaceControl mLeash;
|
||||||
private ViewRootImpl mViewRoot;
|
private ViewRootImpl mViewRoot;
|
||||||
|
private TestHost mTestHost;
|
||||||
private TestHandler mTestHandler;
|
private TestHandler mTestHandler;
|
||||||
private OffsettableClock mTestClock;
|
private OffsettableClock mTestClock;
|
||||||
private static InsetsModeSession sInsetsModeSession;
|
private static InsetsModeSession sInsetsModeSession;
|
||||||
@@ -123,8 +124,8 @@ public class InsetsControllerTest {
|
|||||||
}
|
}
|
||||||
mTestClock = new OffsettableClock();
|
mTestClock = new OffsettableClock();
|
||||||
mTestHandler = new TestHandler(null, mTestClock);
|
mTestHandler = new TestHandler(null, mTestClock);
|
||||||
mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot),
|
mTestHost = new TestHost(mViewRoot);
|
||||||
(controller, type) -> {
|
mController = new InsetsController(mTestHost, (controller, type) -> {
|
||||||
if (type == ITYPE_IME) {
|
if (type == ITYPE_IME) {
|
||||||
return new InsetsSourceConsumer(type, controller.getState(),
|
return new InsetsSourceConsumer(type, controller.getState(),
|
||||||
Transaction::new, controller) {
|
Transaction::new, controller) {
|
||||||
@@ -686,6 +687,24 @@ public class InsetsControllerTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestedState() {
|
||||||
|
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||||
|
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||||
|
mController.hide(statusBars());
|
||||||
|
assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
|
||||||
|
mController.onControlsChanged(new InsetsSourceControl[0]);
|
||||||
|
assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
|
||||||
|
InsetsState newState = new InsetsState(mController.getState(), true /* copySource */);
|
||||||
|
mController.onStateChanged(newState);
|
||||||
|
assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
|
||||||
|
mController.show(statusBars());
|
||||||
|
assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
|
||||||
|
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||||
|
assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void waitUntilNextFrame() throws Exception {
|
private void waitUntilNextFrame() throws Exception {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
|
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
|
||||||
@@ -717,4 +736,23 @@ public class InsetsControllerTest {
|
|||||||
mController.onControlsChanged(controls);
|
mController.onControlsChanged(controls);
|
||||||
return controls;
|
return controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TestHost extends ViewRootInsetsControllerHost {
|
||||||
|
|
||||||
|
private InsetsState mModifiedState = new InsetsState();
|
||||||
|
|
||||||
|
TestHost(ViewRootImpl viewRoot) {
|
||||||
|
super(viewRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInsetsModified(InsetsState insetsState) {
|
||||||
|
mModifiedState = new InsetsState(insetsState, true /* copySource */);
|
||||||
|
super.onInsetsModified(insetsState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsetsState getModifiedState() {
|
||||||
|
return mModifiedState;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user