summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2020-04-22 17:18:25 +0200
committerJorim Jaggi <jjaggi@google.com>2020-04-29 14:00:09 +0200
commitbf87c15b337168bf94f36185cccd46b02aec41a2 (patch)
treeecdb73a71d11f0794086defac73351941e3f1f65 /core/java/android
parent6b25213d686030ed45dc453be7228140ebd8e9ee (diff)
Decouple InsetsController from ViewRootImpl
Such that all it's goodness can also be used in context when ViewRootImpl isn't available, like the SystemUI controller used for Car and Split Test: InsetsControllerTest Fixes: 154631128 Change-Id: I54a3f8a34810472d9273e4627a7811b7abd0863f
Diffstat (limited to 'core/java/android')
-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
4 files changed, 345 insertions, 122 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 8b1e6cbdb6ff..3ce31cb18375 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);
+ }
+}