diff options
| author | 2019-12-05 14:51:09 +0900 | |
|---|---|---|
| committer | 2019-12-27 12:04:54 +0800 | |
| commit | 02abf55ab02cf120850018b05762f9fba5e2afb8 (patch) | |
| tree | 5b3b022dbf7d7d710655ceed4dd503acaff2f16c | |
| parent | 1c1d1c0f0da91cb41a2a72803fd06dc3daf1104b (diff) | |
Decoupling InsetsAnimationControlImpl and the client
Currently InsetsAnimationControlImpl is heavily rely on
InsetsSourceConsumer and InsetsController on the client side, which
caused difficulties to the server to re-use the code. Decoupling it to
make it re-usable.
This patch made the following changes:
1. Introduce a callback interface to let InsetsAnimationControlImpl talk
to InsetsController.
2. Use InsetsSourceControl instead of InsetsSourceConsumer in the
InsetsAnimationControlImpl.
3. Remove all the consumers in the InsetsAnimationControlImpl.
Test: atest InsetsAnimationControlImplTest
Test: manual test with the new insets API, it works as expected.
Test: go/wm-smoke
Test: atest FrameworksCoreTests:InsetsControllerTest
Change-Id: I30f5aa73ff31e07c0dd8d61edbb208f16c5a6775
4 files changed, 122 insertions, 63 deletions
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java new file mode 100644 index 000000000000..6fdadc60afea --- /dev/null +++ b/core/java/android/view/InsetsAnimationControlCallbacks.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 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; + +/** + * Provide an interface to let InsetsAnimationControlImpl call back into its owner. + * @hide + */ +public interface InsetsAnimationControlCallbacks { + /** + * Dispatch the animation started event to all listeners. + * @param animation + */ + void dispatchAnimationStarted(WindowInsetsAnimationCallback.InsetsAnimation animation, + WindowInsetsAnimationCallback.AnimationBounds bounds); + + /** + * Schedule the apply by posting the animation callback. + */ + void scheduleApplyChangeInsets(); + + /** + * Finish the final steps after the animation. + * @param controller The controller used to control the animation. + * @param shown {@code true} if the insets are shown. + */ + void notifyFinished(InsetsAnimationControlImpl controller, boolean shown); + + /** + * Get the description of the insets state. + * @return {@link InsetsState} for adjusting corresponding {@link InsetsSource}. + */ + InsetsState getState(); + + /** + * Apply the new params to the surface. + * @param params The {@link android.view.SyncRtSurfaceTransactionApplier.SurfaceParams} to + * apply. + */ + void applySurfaceParams(SyncRtSurfaceTransactionApplier.SurfaceParams... params); +} diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index cdfd397a732a..771695c2b873 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -40,7 +40,6 @@ import android.view.WindowManager.LayoutParams; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; -import java.util.function.Supplier; /** * Implements {@link WindowInsetsAnimationController} @@ -52,9 +51,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private final Rect mTmpFrame = new Rect(); private final WindowInsetsAnimationControlListener mListener; - private final SparseArray<InsetsSourceConsumer> mConsumers; + private final SparseArray<InsetsSourceControl> mControls; private final SparseIntArray mTypeSideMap = new SparseIntArray(); - private final SparseSetArray<InsetsSourceConsumer> mSideSourceMap = new SparseSetArray<>(); + private final SparseSetArray<InsetsSourceControl> mSideSourceMap = new SparseSetArray<>(); /** @see WindowInsetsAnimationController#getHiddenStateInsets */ private final Insets mHiddenInsets; @@ -64,8 +63,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private final Matrix mTmpMatrix = new Matrix(); private final InsetsState mInitialInsetsState; private final @InsetsType int mTypes; - private final Supplier<SyncRtSurfaceTransactionApplier> mTransactionApplierSupplier; - private final InsetsController mController; + private final InsetsAnimationControlCallbacks mController; private final WindowInsetsAnimationCallback.InsetsAnimation mAnimation; private final Rect mFrame; private final boolean mFade; @@ -79,25 +77,23 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private float mPendingAlpha; @VisibleForTesting - public InsetsAnimationControlImpl(SparseArray<InsetsSourceConsumer> consumers, Rect frame, + public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame, InsetsState state, WindowInsetsAnimationControlListener listener, @InsetsType int types, - Supplier<SyncRtSurfaceTransactionApplier> transactionApplierSupplier, - InsetsController controller, long durationMs, boolean fade) { - mConsumers = consumers; + InsetsAnimationControlCallbacks controller, long durationMs, boolean fade) { + mControls = controls; mListener = listener; mTypes = types; mFade = fade; - mTransactionApplierSupplier = transactionApplierSupplier; mController = controller; mInitialInsetsState = new InsetsState(state, true /* copySources */); mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* typeSideMap */); - mHiddenInsets = calculateInsets(mInitialInsetsState, frame, consumers, false /* shown */, + mHiddenInsets = calculateInsets(mInitialInsetsState, frame, controls, false /* shown */, null /* typeSideMap */); - mShownInsets = calculateInsets(mInitialInsetsState, frame, consumers, true /* shown */, + mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */, mTypeSideMap); mFrame = new Rect(frame); - buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mConsumers); + buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls); // TODO: Check for controllability first and wait for IME if needed. listener.onReady(this, types); @@ -172,8 +168,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll updateLeashesForSide(ISIDE_FLOATING, 0 /* offset */, 0 /* inset */, 0 /* maxInset */, params, state, alphaOffset); - SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get(); - applier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); + mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()])); mCurrentInsets = mPendingInsets; mAnimation.setFraction(mPendingFraction); mCurrentAlpha = 1 - alphaOffset; @@ -189,9 +184,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll return; } InsetsState state = new InsetsState(mController.getState()); - for (int i = mConsumers.size() - 1; i >= 0; i--) { - InsetsSourceConsumer consumer = mConsumers.valueAt(i); - state.getSource(consumer.getType()).setVisible(shown); + for (int i = mControls.size() - 1; i >= 0; i--) { + InsetsSourceControl control = mControls.valueAt(i); + state.getSource(control.getType()).setVisible(shown); } Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */); setInsetsAndAlpha(insets, 1f /* alpha */, shown ? 1f : 0f /* fraction */); @@ -222,10 +217,12 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll } private Insets calculateInsets(InsetsState state, Rect frame, - SparseArray<InsetsSourceConsumer> consumers, boolean shown, + SparseArray<InsetsSourceControl> controls, boolean shown, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { - for (int i = consumers.size() - 1; i >= 0; i--) { - state.getSource(consumers.valueAt(i).getType()).setVisible(shown); + for (int i = controls.size() - 1; i >= 0; i--) { + // control may be null if it got revoked. + if (controls.valueAt(i) == null) continue; + state.getSource(controls.valueAt(i).getType()).setVisible(shown); } return getInsetsFromState(state, frame, typeSideMap); } @@ -233,7 +230,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private Insets getInsetsFromState(InsetsState state, Rect frame, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { return state.calculateInsets(frame, false /* isScreenRound */, - false /* alwaysConsumerNavBar */, null /* displayCutout */, + false /* alwaysConsumeSystemBars */, null /* displayCutout */, null /* legacyContentInsets */, null /* legacyStableInsets */, LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, typeSideMap) .getInsets(mTypes); @@ -252,20 +249,19 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset, int maxInset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) { - ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side); + ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side); if (items == null) { return; } // TODO: Implement behavior when inset spans over multiple types for (int i = items.size() - 1; i >= 0; i--) { - final InsetsSourceConsumer consumer = items.valueAt(i); - final InsetsSource source = mInitialInsetsState.getSource(consumer.getType()); - final InsetsSourceControl control = consumer.getControl(); + final InsetsSourceControl control = items.valueAt(i); + final InsetsSource source = mInitialInsetsState.getSource(control.getType()); if (control == null) { - // Control may not be available for consumer yet or revoked. + // TODO: remove this check when we ensure the elements will not be null. continue; } - final SurfaceControl leash = consumer.getControl().getLeash(); + final SurfaceControl leash = control.getLeash(); mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y); mTmpFrame.set(source.getFrame()); @@ -279,7 +275,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll alpha = mFade ? ((float) maxInset / inset * 0.3f + 0.7f) : alpha; surfaceParams.add(new SurfaceParams(leash, alpha, mTmpMatrix, null /* windowCrop */, 0 /* layer */, 0f /* cornerRadius*/, - side == ISIDE_FLOATING ? consumer.isVisible() : inset != 0 /* visible */)); + side == ISIDE_FLOATING ? state.getSource(source.getType()).isVisible() + : inset != 0 /* visible */)); } } } @@ -307,18 +304,18 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll } private static void buildTypeSourcesMap(SparseIntArray typeSideMap, - SparseSetArray<InsetsSourceConsumer> sideSourcesMap, - SparseArray<InsetsSourceConsumer> consumers) { + SparseSetArray<InsetsSourceControl> sideSourcesMap, + SparseArray<InsetsSourceControl> controls) { for (int i = typeSideMap.size() - 1; i >= 0; i--) { final int type = typeSideMap.keyAt(i); final int side = typeSideMap.valueAt(i); - final InsetsSourceConsumer consumer = consumers.get(type); - if (consumer == null) { + final InsetsSourceControl control = controls.get(type); + if (control == null) { // If the types that we are controlling are less than the types that the system has, - // there can be some null consumers. + // there can be some null controllers. continue; } - sideSourcesMap.add(side, consumer); + sideSourcesMap.add(side, control); } } } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 5563d629f25e..4d4ace27cac9 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -53,7 +53,7 @@ import java.util.ArrayList; * Implements {@link WindowInsetsController} on the client. * @hide */ -public class InsetsController implements WindowInsetsController { +public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks { private static final int ANIMATION_DURATION_SHOW_MS = 275; private static final int ANIMATION_DURATION_HIDE_MS = 340; @@ -186,6 +186,8 @@ public class InsetsController implements WindowInsetsController { private int mLastLegacySoftInputMode; + private SyncRtSurfaceTransactionApplier mApplier; + public InsetsController(ViewRootImpl viewRoot) { mViewRoot = viewRoot; mAnimCallback = () -> { @@ -375,9 +377,10 @@ public class InsetsController implements WindowInsetsController { final ArraySet<Integer> internalTypes = mState.toInternalType(types); final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); + final SparseArray<InsetsSourceControl> controls = new SparseArray<>(); - Pair<Integer, Boolean> typesReadyPair = collectConsumers( - fromIme, internalTypes, consumers, listener); + Pair<Integer, Boolean> typesReadyPair = collectSourceControls( + fromIme, internalTypes, controls, listener); int typesReady = typesReadyPair.first; boolean isReady = typesReadyPair.second; if (!isReady) { @@ -388,24 +391,23 @@ public class InsetsController implements WindowInsetsController { } // pending types from previous request. - typesReady = collectPendingConsumers(typesReady, consumers); + typesReady = collectPendingTypes(typesReady); if (typesReady == 0) { listener.onCancelled(); return; } - final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers, - frame, mState, listener, typesReady, - () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this, durationMs, fade); + final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls, + frame, mState, listener, typesReady, this, durationMs, fade); mAnimationControls.add(controller); } /** * @return Pair of (types ready to animate, is ready to animate). */ - private Pair<Integer, Boolean> collectConsumers(boolean fromIme, - ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers, + private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, + ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls, WindowInsetsAnimationControlListener listener) { int typesReady = 0; boolean isReady = true; @@ -439,22 +441,14 @@ public class InsetsController implements WindowInsetsController { } typesReady |= InsetsState.toPublicType(consumer.getType()); } - consumers.put(consumer.getType(), consumer); + controls.put(consumer.getType(), consumer.getControl()); } return new Pair<>(typesReady, isReady); } - private int collectPendingConsumers(@InsetsType int typesReady, - SparseArray<InsetsSourceConsumer> consumers) { - if (mPendingTypesToShow != 0) { - typesReady |= mPendingTypesToShow; - final ArraySet<Integer> internalTypes = mState.toInternalType(mPendingTypesToShow); - for (int i = internalTypes.size() - 1; i >= 0; i--) { - InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); - consumers.put(consumer.getType(), consumer); - } - mPendingTypesToShow = 0; - } + private int collectPendingTypes(@InsetsType int typesReady) { + typesReady |= mPendingTypesToShow; + mPendingTypesToShow = 0; return typesReady; } @@ -468,6 +462,7 @@ public class InsetsController implements WindowInsetsController { } @VisibleForTesting + @Override public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) { mAnimationControls.remove(controller); if (shown) { @@ -477,6 +472,17 @@ public class InsetsController implements WindowInsetsController { } } + @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); + } + mApplier.scheduleApply(params); + } + void notifyControlRevoked(InsetsSourceConsumer consumer) { for (int i = mAnimationControls.size() - 1; i >= 0; i--) { InsetsAnimationControlImpl control = mAnimationControls.get(i); @@ -620,6 +626,7 @@ public class InsetsController implements WindowInsetsController { } @VisibleForTesting + @Override public void dispatchAnimationStarted(InsetsAnimation animation, AnimationBounds bounds) { mViewRoot.mView.dispatchWindowInsetsAnimationStarted(animation, bounds); } @@ -630,6 +637,7 @@ public class InsetsController implements WindowInsetsController { } @VisibleForTesting + @Override public void scheduleApplyChangeInsets() { if (!mAnimCallbackScheduled) { mViewRoot.mChoreographer.postCallback(Choreographer.CALLBACK_INSETS_ANIMATION, diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index 68d95cd38497..179929f2aae0 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -76,7 +76,6 @@ public class InsetsAnimationControlImplTest { @Mock Transaction mMockTransaction; @Mock InsetsController mMockController; @Mock WindowInsetsAnimationControlListener mMockListener; - @Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier; @BeforeClass public static void setupOnce() { @@ -111,12 +110,12 @@ public class InsetsAnimationControlImplTest { navConsumer.setControl(new InsetsSourceControl(ITYPE_NAVIGATION_BAR, mNavLeash, new Point(400, 0))); - SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); - consumers.put(ITYPE_STATUS_BAR, topConsumer); - consumers.put(ITYPE_NAVIGATION_BAR, navConsumer); - mController = new InsetsAnimationControlImpl(consumers, + SparseArray<InsetsSourceControl> controls = new SparseArray<>(); + controls.put(ITYPE_STATUS_BAR, topConsumer.getControl()); + controls.put(ITYPE_NAVIGATION_BAR, navConsumer.getControl()); + mController = new InsetsAnimationControlImpl(controls, new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(), - () -> mMockTransactionApplier, mMockController, 10 /* durationMs */, + mMockController, 10 /* durationMs */, false /* fade */); } @@ -137,7 +136,7 @@ public class InsetsAnimationControlImplTest { assertEquals(1f, mController.getCurrentAlpha(), 1f - mController.getCurrentAlpha()); ArgumentCaptor<SurfaceParams> captor = ArgumentCaptor.forClass(SurfaceParams.class); - verify(mMockTransactionApplier).scheduleApply(captor.capture()); + verify(mMockController).applySurfaceParams(captor.capture()); List<SurfaceParams> params = captor.getAllValues(); assertEquals(2, params.size()); SurfaceParams first = params.get(0); |