diff options
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(); |