summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/ImeInsetsSourceConsumer.java2
-rw-r--r--core/java/android/view/InsetsController.java248
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/view/ViewRootInsetsControllerHost.java215
-rw-r--r--core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java3
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java3
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java3
7 files changed, 351 insertions, 125 deletions
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index df891303bb1d..38b6c03a02f9 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -217,6 +217,6 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
}
private InputMethodManager getImm() {
- return mController.getViewRoot().mContext.getSystemService(InputMethodManager.class);
+ return mController.getHost().getInputMethodManager();
}
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index f135328c44fe..887607972bbc 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -37,9 +37,7 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.RemoteException;
import android.util.ArraySet;
-import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.InsetsSourceConsumer.ShowResult;
@@ -53,6 +51,7 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
+import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -72,6 +71,91 @@ import java.util.function.BiFunction;
*/
public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks {
+ public interface Host {
+
+ Handler getHandler();
+
+ /**
+ * Notifies host that {@link InsetsController#getState()} has changed.
+ */
+ void notifyInsetsChanged();
+
+ void dispatchWindowInsetsAnimationPrepare(@NonNull WindowInsetsAnimation animation);
+ Bounds dispatchWindowInsetsAnimationStart(
+ @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds);
+ WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
+ @NonNull List<WindowInsetsAnimation> runningAnimations);
+ void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation);
+
+ /**
+ * Requests host to apply surface params in synchronized manner.
+ */
+ void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params);
+
+ /**
+ * @see ViewRootImpl#updateCompatSysUiVisibility(int, boolean, boolean)
+ */
+ void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
+ boolean hasControl);
+
+ /**
+ * Called when insets have been modified by the client and should be reported back to WM.
+ */
+ void onInsetsModified(InsetsState insetsState);
+
+ /**
+ * @return Whether the host has any callbacks it wants to synchronize the animations with.
+ * If there are no callbacks, the animation will be off-loaded to another thread and
+ * slightly different animation curves are picked.
+ */
+ boolean hasAnimationCallbacks();
+
+ /**
+ * @see WindowInsetsController#setSystemBarsAppearance
+ */
+ void setSystemBarsAppearance(@Appearance int appearance, @Appearance int mask);
+
+ /**
+ * @see WindowInsetsController#getSystemBarsAppearance()
+ */
+ @Appearance int getSystemBarsAppearance();
+
+ /**
+ * @see WindowInsetsController#setSystemBarsBehavior
+ */
+ void setSystemBarsBehavior(@Behavior int behavior);
+
+ /**
+ * @see WindowInsetsController#getSystemBarsBehavior
+ */
+ @Behavior int getSystemBarsBehavior();
+
+ /**
+ * Releases a surface and ensure that this is done after {@link #applySurfaceParams} has
+ * finished applying params.
+ */
+ void releaseSurfaceControlFromRt(SurfaceControl surfaceControl);
+
+ /**
+ * If this host is a view hierarchy, adds a pre-draw runnable to ensure proper ordering as
+ * described in {@link WindowInsetsAnimation.Callback#onPrepare}.
+ *
+ * If this host isn't a view hierarchy, the runnable can be executed immediately.
+ */
+ void addOnPreDrawRunnable(Runnable r);
+
+ /**
+ * Adds a runnbale to be executed during {@link Choreographer#CALLBACK_INSETS_ANIMATION}
+ * phase.
+ */
+ void postInsetsAnimationCallback(Runnable r);
+
+ /**
+ * Obtains {@link InputMethodManager} instance from host.
+ */
+ InputMethodManager getInputMethodManager();
+ }
+
private static final int ANIMATION_DURATION_SHOW_MS = 275;
private static final int ANIMATION_DURATION_HIDE_MS = 340;
@@ -346,7 +430,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private final Rect mFrame = new Rect();
private final BiFunction<InsetsController, Integer, InsetsSourceConsumer> mConsumerCreator;
private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
- private final ViewRootImpl mViewRoot;
+ private final Host mHost;
private final Handler mHandler;
private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
@@ -370,8 +454,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private boolean mStartingAnimation;
private int mCaptionInsetsHeight = 0;
- private SyncRtSurfaceTransactionApplier mApplier;
-
private Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
= new ArrayList<>();
@@ -379,22 +461,22 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
/** Set of inset types for which an animation was started since last resetting this field */
private @InsetsType int mLastStartedAnimTypes;
- public InsetsController(ViewRootImpl viewRoot) {
- this(viewRoot, (controller, type) -> {
+ public InsetsController(Host host) {
+ this(host, (controller, type) -> {
if (type == ITYPE_IME) {
return new ImeInsetsSourceConsumer(controller.mState, Transaction::new, controller);
} else {
return new InsetsSourceConsumer(type, controller.mState, Transaction::new,
controller);
}
- }, viewRoot.mHandler);
+ }, host.getHandler());
}
@VisibleForTesting
- public InsetsController(ViewRootImpl viewRoot,
+ public InsetsController(Host host,
BiFunction<InsetsController, Integer, InsetsSourceConsumer> consumerCreator,
Handler handler) {
- mViewRoot = viewRoot;
+ mHost = host;
mConsumerCreator = consumerCreator;
mHandler = handler;
mAnimCallback = () -> {
@@ -402,10 +484,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (mRunningAnimations.isEmpty()) {
return;
}
- if (mViewRoot.mView == null) {
- // The view has already detached from window.
- return;
- }
mTmpFinishedControls.clear();
mTmpRunningAnims.clear();
@@ -433,8 +511,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags,
null /* typeSideMap */);
- mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets,
- mUnmodifiableTmpRunningAnims);
+ mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims);
for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation());
@@ -447,7 +524,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (mFrame.equals(frame)) {
return;
}
- mViewRoot.notifyInsetsChanged();
+ mHost.notifyInsetsChanged();
mFrame.set(frame);
}
@@ -476,7 +553,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mLastDispachedState.set(state, true /* copySources */);
applyLocalVisibilityOverride();
if (localStateChanged) {
- mViewRoot.notifyInsetsChanged();
+ mHost.notifyInsetsChanged();
}
if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
sendStateToWindowManager();
@@ -733,7 +810,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
final InsetsAnimationControlRunner runner = useInsetsAnimationThread
? new InsetsAnimationThreadControlRunner(controls,
frame, mState, listener, typesReady, this, durationMs, interpolator,
- animationType, mViewRoot.mHandler)
+ animationType, mHost.getHandler())
: new InsetsAnimationControlImpl(controls,
frame, mState, listener, typesReady, this, durationMs, interpolator,
animationType);
@@ -860,21 +937,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@Override
public void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
- if (mApplier == null) {
- if (mViewRoot.mView == null) {
- throw new IllegalStateException("View of the ViewRootImpl is not initiated.");
- }
- mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
- }
- if (mViewRoot.mView.isHardwareAccelerated()) {
- mApplier.scheduleApply(false /* earlyWakeup */, params);
- } else {
- // Window doesn't support hardware acceleration, no synchronization for now.
- // TODO(b/149342281): use mViewRoot.mSurface.getNextFrameNumber() to sync on every
- // frame instead.
- mApplier.applyParams(new Transaction(), -1 /* frame */, false /* earlyWakeup */,
- params);
- }
+ mHost.applySurfaceParams(params);
}
void notifyControlRevoked(InsetsSourceConsumer consumer) {
@@ -900,7 +963,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
ArraySet<Integer> types = toInternalType(control.getTypes());
for (int j = types.size() - 1; j >= 0; j--) {
if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
- mViewRoot.notifyInsetsChanged();
+ mHost.notifyInsetsChanged();
}
}
break;
@@ -928,7 +991,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@VisibleForTesting
public void notifyVisibilityChanged() {
- mViewRoot.notifyInsetsChanged();
+ mHost.notifyInsetsChanged();
sendStateToWindowManager();
}
@@ -937,7 +1000,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
*/
public void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
boolean hasControl) {
- mViewRoot.updateCompatSysUiVisibility(type, visible, hasControl);
+ mHost.updateCompatSysUiVisibility(type, visible, hasControl);
}
/**
@@ -954,10 +1017,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
getSourceConsumer(ITYPE_IME).onWindowFocusLost();
}
- ViewRootImpl getViewRoot() {
- return mViewRoot;
- }
-
/**
* Used by {@link ImeInsetsSourceConsumer} when IME decides to be shown/hidden.
* @hide
@@ -994,12 +1053,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
tmpState.addSource(mState.getSource(consumer.getType()));
}
}
-
- try {
- mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, tmpState);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to call insetsModified", e);
- }
+ mHost.onInsetsModified(tmpState);
}
@VisibleForTesting
@@ -1009,7 +1063,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
return;
}
- boolean hasAnimationCallbacks = hasAnimationCallbacks();
+ boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks();
final InternalAnimationControlListener listener =
new InternalAnimationControlListener(show, hasAnimationCallbacks, types);
@@ -1024,13 +1078,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
- private boolean hasAnimationCallbacks() {
- if (mViewRoot.mView == null) {
- return false;
- }
- return mViewRoot.mView.hasWindowInsetsAnimationCallback();
- }
-
private void hideDirectly(
@InsetsType int types, boolean animationFinished, @AnimationType int animationType) {
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
@@ -1064,37 +1111,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
public void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
WindowInsetsAnimation animation, Bounds bounds) {
- if (mViewRoot.mView == null) {
- return;
- }
- mViewRoot.mView.dispatchWindowInsetsAnimationPrepare(animation);
- mViewRoot.mView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mViewRoot.mView.getViewTreeObserver().removeOnPreDrawListener(this);
- if (controller.isCancelled()) {
- return true;
- }
- for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
- RunningAnimation runningAnimation = mRunningAnimations.get(i);
- if (runningAnimation.runner == controller) {
- runningAnimation.startDispatched = true;
- }
+ mHost.dispatchWindowInsetsAnimationPrepare(animation);
+ mHost.addOnPreDrawRunnable(() -> {
+ if (controller.isCancelled()) {
+ return;
+ }
+ for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
+ RunningAnimation runningAnimation = mRunningAnimations.get(i);
+ if (runningAnimation.runner == controller) {
+ runningAnimation.startDispatched = true;
}
- mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds);
- mStartingAnimation = true;
- controller.mReadyDispatched = true;
- listener.onReady(controller, types);
- mStartingAnimation = false;
- return true;
}
+ mHost.dispatchWindowInsetsAnimationStart(animation, bounds);
+ mStartingAnimation = true;
+ controller.mReadyDispatched = true;
+ listener.onReady(controller, types);
+ mStartingAnimation = false;
});
- mViewRoot.mView.invalidate();
}
@VisibleForTesting
public void dispatchAnimationEnd(WindowInsetsAnimation animation) {
- mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
+ mHost.dispatchWindowInsetsAnimationEnd(animation);
}
@VisibleForTesting
@@ -1106,30 +1144,19 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
return;
}
if (!mAnimCallbackScheduled) {
- mViewRoot.mChoreographer.postCallback(Choreographer.CALLBACK_INSETS_ANIMATION,
- mAnimCallback, null /* token*/);
+ mHost.postInsetsAnimationCallback(mAnimCallback);
mAnimCallbackScheduled = true;
}
}
@Override
public void setSystemBarsAppearance(@Appearance int appearance, @Appearance int mask) {
- mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
- final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags;
- if (insetsFlags.appearance != appearance) {
- insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
- mViewRoot.mWindowAttributesChanged = true;
- mViewRoot.scheduleTraversals();
- }
+ mHost.setSystemBarsAppearance(appearance, mask);
}
@Override
public @Appearance int getSystemBarsAppearance() {
- if ((mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
- // We only return the requested appearance, not the implied one.
- return 0;
- }
- return mViewRoot.mWindowAttributes.insetsFlags.appearance;
+ return mHost.getSystemBarsAppearance();
}
@Override
@@ -1139,21 +1166,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@Override
public void setSystemBarsBehavior(@Behavior int behavior) {
- mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
- if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
- mViewRoot.mWindowAttributes.insetsFlags.behavior = behavior;
- mViewRoot.mWindowAttributesChanged = true;
- mViewRoot.scheduleTraversals();
- }
+ mHost.setSystemBarsBehavior(behavior);
}
@Override
public @Appearance int getSystemBarsBehavior() {
- if ((mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_BEHAVIOR_CONTROLLED) == 0) {
- // We only return the requested behavior, not the implied one.
- return 0;
- }
- return mViewRoot.mWindowAttributes.insetsFlags.behavior;
+ return mHost.getSystemBarsBehavior();
}
private @InsetsType int calculateControllableTypes() {
@@ -1198,22 +1216,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mControllableInsetsChangedListeners.remove(listener);
}
- /**
- * At the time we receive new leashes (e.g. InsetsSourceConsumer is processing
- * setControl) we need to release the old leash. But we may have already scheduled
- * a SyncRtSurfaceTransaction applier to use it from the RenderThread. To avoid
- * synchronization issues we also release from the RenderThread so this release
- * happens after any existing items on the work queue.
- */
+ @Override
public void releaseSurfaceControlFromRt(SurfaceControl sc) {
- if (mViewRoot.mView != null && mViewRoot.mView.isHardwareAccelerated()) {
- mViewRoot.registerRtFrameCallback(frame -> {
- sc.release();
- });
- // Make sure a frame gets scheduled.
- mViewRoot.mView.invalidate();
- } else {
- sc.release();
- }
+ mHost.releaseSurfaceControlFromRt(sc);
+ }
+
+ Host getHost() {
+ return mHost;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6f85072a0472..b74c8f641a76 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -757,7 +757,7 @@ public final class ViewRootImpl implements ViewParent,
mChoreographer = useSfChoreographer
? Choreographer.getSfInstance() : Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- mInsetsController = new InsetsController(this);
+ mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));
String processorOverrideName = context.getResources().getString(
R.string.config_inputEventCompatProcessorOverrideClassName);
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
new file mode 100644
index 000000000000..d8bf58f78339
--- /dev/null
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import java.util.List;
+
+/**
+ * Implements {@link InsetsController.Host} for {@link ViewRootImpl}s.
+ * @hide
+ */
+public class ViewRootInsetsControllerHost implements InsetsController.Host {
+
+ private final String TAG = "VRInsetsControllerHost";
+
+ private final ViewRootImpl mViewRoot;
+ private SyncRtSurfaceTransactionApplier mApplier;
+
+ public ViewRootInsetsControllerHost(ViewRootImpl viewRoot) {
+ mViewRoot = viewRoot;
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mViewRoot.mHandler;
+ }
+
+ @Override
+ public void notifyInsetsChanged() {
+ mViewRoot.notifyInsetsChanged();
+ }
+
+ @Override
+ public void addOnPreDrawRunnable(Runnable r) {
+ if (mViewRoot.mView == null) {
+ return;
+ }
+ mViewRoot.mView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mViewRoot.mView.getViewTreeObserver().removeOnPreDrawListener(this);
+ r.run();
+ return true;
+ }
+ });
+ mViewRoot.mView.invalidate();
+ }
+
+ @Override
+ public void dispatchWindowInsetsAnimationPrepare(@NonNull WindowInsetsAnimation animation) {
+ if (mViewRoot.mView == null) {
+ return;
+ }
+ mViewRoot.mView.dispatchWindowInsetsAnimationPrepare(animation);
+ }
+
+ @Override
+ public WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart(
+ @NonNull WindowInsetsAnimation animation,
+ @NonNull WindowInsetsAnimation.Bounds bounds) {
+ if (mViewRoot.mView == null) {
+ return null;
+ }
+ return mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds);
+ }
+
+ @Override
+ public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
+ @NonNull List<WindowInsetsAnimation> runningAnimations) {
+ if (mViewRoot.mView == null) {
+ // The view has already detached from window.
+ return null;
+ }
+ return mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets, runningAnimations);
+ }
+
+ @Override
+ public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
+ mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
+ }
+
+ @Override
+ public void applySurfaceParams(SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
+ if (mApplier == null) {
+ if (mViewRoot.mView == null) {
+ throw new IllegalStateException("View of the ViewRootImpl is not initiated.");
+ }
+ mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
+ }
+ if (mViewRoot.mView.isHardwareAccelerated()) {
+ mApplier.scheduleApply(false /* earlyWakeup */, params);
+ } else {
+ // Window doesn't support hardware acceleration, no synchronization for now.
+ // TODO(b/149342281): use mViewRoot.mSurface.getNextFrameNumber() to sync on every
+ // frame instead.
+ mApplier.applyParams(new SurfaceControl.Transaction(), -1 /* frame */,
+ false /* earlyWakeup */, params);
+ }
+ }
+
+ @Override
+ public void postInsetsAnimationCallback(Runnable r) {
+ mViewRoot.mChoreographer.postCallback(Choreographer.CALLBACK_INSETS_ANIMATION, r,
+ null /* token */);
+ }
+
+ @Override
+ public void updateCompatSysUiVisibility(int type, boolean visible, boolean hasControl) {
+ mViewRoot.updateCompatSysUiVisibility(type, visible, hasControl);
+ }
+
+ @Override
+ public void onInsetsModified(InsetsState insetsState) {
+ try {
+ mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call insetsModified", e);
+ }
+ }
+
+ @Override
+ public boolean hasAnimationCallbacks() {
+ if (mViewRoot.mView == null) {
+ return false;
+ }
+ return mViewRoot.mView.hasWindowInsetsAnimationCallback();
+ }
+
+ @Override
+ public void setSystemBarsAppearance(int appearance, int mask) {
+ mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
+ final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags;
+ if (insetsFlags.appearance != appearance) {
+ insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
+ mViewRoot.mWindowAttributesChanged = true;
+ mViewRoot.scheduleTraversals();
+ }
+ }
+
+ @Override
+ public int getSystemBarsAppearance() {
+ if ((mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
+ // We only return the requested appearance, not the implied one.
+ return 0;
+ }
+ return mViewRoot.mWindowAttributes.insetsFlags.appearance;
+ }
+
+ @Override
+ public void setSystemBarsBehavior(int behavior) {
+ mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
+ if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
+ mViewRoot.mWindowAttributes.insetsFlags.behavior = behavior;
+ mViewRoot.mWindowAttributesChanged = true;
+ mViewRoot.scheduleTraversals();
+ }
+ }
+
+ @Override
+ public int getSystemBarsBehavior() {
+ if ((mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_BEHAVIOR_CONTROLLED) == 0) {
+ // We only return the requested behavior, not the implied one.
+ return 0;
+ }
+ return mViewRoot.mWindowAttributes.insetsFlags.behavior;
+ }
+
+ @Override
+ public void releaseSurfaceControlFromRt(SurfaceControl surfaceControl) {
+
+ // At the time we receive new leashes (e.g. InsetsSourceConsumer is processing
+ // setControl) we need to release the old leash. But we may have already scheduled
+ // a SyncRtSurfaceTransaction applier to use it from the RenderThread. To avoid
+ // synchronization issues we also release from the RenderThread so this release
+ // happens after any existing items on the work queue.
+
+ if (mViewRoot.mView != null && mViewRoot.mView.isHardwareAccelerated()) {
+ mViewRoot.registerRtFrameCallback(frame -> {
+ surfaceControl.release();
+ });
+ // Make sure a frame gets scheduled.
+ mViewRoot.mView.invalidate();
+ } else {
+ surfaceControl.release();
+ }
+ }
+
+ @Override
+ public InputMethodManager getInputMethodManager() {
+ return mViewRoot.mContext.getSystemService(InputMethodManager.class);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 5c9e3397c6a5..164c372768c0 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -78,7 +78,8 @@ public class ImeInsetsSourceConsumerTest {
} catch (BadTokenException e) {
// activity isn't running, we will ignore BadTokenException.
}
- mController = Mockito.spy(new InsetsController(viewRootImpl));
+ mController = Mockito.spy(new InsetsController(
+ new ViewRootInsetsControllerHost(viewRootImpl)));
final Rect rect = new Rect(5, 5, 5, 5);
mController.calculateInsets(
false,
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index ade31d8e4173..ccf4192ac2f4 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -123,7 +123,8 @@ public class InsetsControllerTest {
}
mTestClock = new OffsettableClock();
mTestHandler = new TestHandler(null, mTestClock);
- mController = new InsetsController(mViewRoot, (controller, type) -> {
+ mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot),
+ (controller, type) -> {
if (type == ITYPE_IME) {
return new InsetsSourceConsumer(type, controller.getState(),
Transaction::new, controller) {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index cc93f9a5b59c..25f94131f820 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -89,7 +89,8 @@ public class InsetsSourceConsumerTest {
state.addSource(mSpyInsetsSource);
mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, state,
- () -> mMockTransaction, new InsetsController(viewRootImpl));
+ () -> mMockTransaction,
+ new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl)));
});
instrumentation.waitForIdleSync();