Merge "Decoupling InsetsAnimationControlImpl and the client"

This commit is contained in:
TreeHugger Robot
2019-12-27 05:38:51 +00:00
committed by Android (Google) Code Review
4 changed files with 122 additions and 63 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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,