Merge "Implement Transient Insets Animation"

This commit is contained in:
TreeHugger Robot
2020-02-03 05:44:38 +00:00
committed by Android (Google) Code Review
5 changed files with 184 additions and 23 deletions

View File

@@ -16,8 +16,6 @@
package android.view;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_FLOATING;
import static android.view.InsetsState.ISIDE_LEFT;
@@ -188,7 +186,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
@Override
public void finish(boolean shown) {
if (mCancelled) {
if (mCancelled || mFinished) {
return;
}
setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */);

View File

@@ -70,7 +70,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private static final int ANIMATION_DURATION_HIDE_MS = 340;
private static final int PENDING_CONTROL_TIMEOUT_MS = 2000;
static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
public static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
/**
* Layout mode during insets animation: The views should be laid out as if the changing inset
@@ -78,7 +78,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
* be called as if the changing insets types are shown, which will result in the views being
* laid out as if the insets are fully shown.
*/
static final int LAYOUT_INSETS_DURING_ANIMATION_SHOWN = 0;
public static final int LAYOUT_INSETS_DURING_ANIMATION_SHOWN = 0;
/**
* Layout mode during insets animation: The views should be laid out as if the changing inset
@@ -86,7 +86,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
* be called as if the changing insets types are hidden, which will result in the views being
* laid out as if the insets are fully hidden.
*/
static final int LAYOUT_INSETS_DURING_ANIMATION_HIDDEN = 1;
public static final int LAYOUT_INSETS_DURING_ANIMATION_HIDDEN = 1;
/**
* Determines the behavior of how the views should be laid out during an insets animation that
@@ -149,7 +149,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@Override
public void set(WindowInsetsAnimationController controller, Insets value) {
controller.setInsetsAndAlpha(
value, 1f /* alpha */, (((DefaultAnimationControlListener)
value, 1f /* alpha */, (((InternalAnimationControlListener)
((InsetsAnimationControlImpl) controller).getListener())
.getRawFraction()));
}
@@ -166,7 +166,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private ObjectAnimator mAnimator;
protected boolean mShow;
InternalAnimationControlListener(boolean show) {
public InternalAnimationControlListener(boolean show) {
mShow = show;
}
@@ -214,7 +214,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
return (float) mAnimator.getCurrentPlayTime() / mAnimator.getDuration();
}
protected long getDurationMs() {
/**
* To get the animation duration in MS.
*/
public long getDurationMs() {
if (mAnimator != null) {
return mAnimator.getDuration();
}

View File

@@ -193,6 +193,15 @@ public class InsetsSource implements Parcelable {
dest.writeBoolean(mVisible);
}
@Override
public String toString() {
return "InsetsSource: {"
+ "mType=" + InsetsState.typeToString(mType)
+ ", mFrame=" + mFrame.toShortString()
+ ", mVisible" + mVisible
+ "}";
}
public static final @android.annotation.NonNull Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {
public InsetsSource createFromParcel(Parcel in) {

View File

@@ -21,7 +21,6 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.IME;
import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
@@ -43,7 +42,6 @@ import android.util.ArraySet;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import java.io.PrintWriter;
@@ -366,7 +364,12 @@ public class InsetsState implements Parcelable {
return result;
}
static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
/**
* Converting a internal type to the public type.
* @param type internal insets type, {@code InternalInsetsType}.
* @return public insets type, {@code Type.InsetsType}.
*/
public static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
switch (type) {
case ITYPE_STATUS_BAR:
return Type.STATUS_BARS;
@@ -510,5 +513,13 @@ public class InsetsState implements Parcelable {
mSources.put(source.getType(), source);
}
}
@Override
public String toString() {
return "InsetsState: {"
+ "mDisplayFrame=" + mDisplayFrame
+ ", mSources=" + mSources
+ "}";
}
}

View File

@@ -20,17 +20,31 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.util.IntArray;
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
import android.view.InsetsAnimationControlImpl;
import android.view.InsetsController;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimationCallback;
import android.view.WindowInsetsAnimationControlListener;
import com.android.server.DisplayThread;
/**
* Policy that implements who gets control over the windows generating insets.
@@ -46,6 +60,8 @@ class InsetsPolicy {
private WindowState mFocusedWin;
private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
private boolean mAnimatingShown;
private final float[] mTmpFloat9 = new float[9];
InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
mStateController = stateController;
@@ -91,11 +107,14 @@ class InsetsPolicy {
changed = true;
}
if (changed) {
updateBarControlTarget(mFocusedWin);
mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
mShowingTransientTypes.toArray());
mStateController.notifyInsetsChanged();
// TODO(b/118118435): Animation
startAnimation(mShowingTransientTypes, true, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mPolicy.getStatusBarManagerInternal().showTransient(
mDisplayContent.getDisplayId(),
mShowingTransientTypes.toArray());
mStateController.notifyInsetsChanged();
}
});
}
}
@@ -103,11 +122,13 @@ class InsetsPolicy {
if (mShowingTransientTypes.size() == 0) {
return;
}
// TODO(b/118118435): Animation
mShowingTransientTypes.clear();
updateBarControlTarget(mFocusedWin);
mStateController.notifyInsetsChanged();
startAnimation(mShowingTransientTypes, false, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mShowingTransientTypes.clear();
mStateController.notifyInsetsChanged();
updateBarControlTarget(mFocusedWin);
}
});
}
boolean isTransient(@InternalInsetsType int type) {
@@ -247,6 +268,29 @@ class InsetsPolicy {
return isDockedStackVisible || isFreeformStackVisible || isResizing;
}
private void startAnimation(IntArray internalTypes, boolean show, Runnable callback) {
int typesReady = 0;
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
updateBarControlTarget(mFocusedWin);
for (int i = internalTypes.size() - 1; i >= 0; i--) {
InsetsSourceProvider provider =
mStateController.getSourceProvider(internalTypes.get(i));
if (provider == null) continue;
InsetsSourceControl control = provider.getControl(provider.getControlTarget());
if (control == null || control.getLeash() == null) continue;
typesReady |= InsetsState.toPublicType(internalTypes.get(i));
controls.put(control.getType(), control);
}
controlAnimationUnchecked(typesReady, controls, show, callback);
}
private void controlAnimationUnchecked(int typesReady,
SparseArray<InsetsSourceControl> controls, boolean show, Runnable callback) {
InsetsPolicyAnimationControlListener listener =
new InsetsPolicyAnimationControlListener(show, callback);
listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show);
}
private class BarWindow {
private final int mId;
@@ -267,7 +311,103 @@ class InsetsPolicy {
}
}
// TODO(b/118118435): Implement animations for it (with SurfaceAnimator)
private class InsetsPolicyAnimationControlListener extends
InsetsController.InternalAnimationControlListener {
Runnable mFinishCallback;
InsetsPolicyAnimationControlCallbacks mControlCallbacks;
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback) {
super(show);
mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
}
@Override
protected void onAnimationFinish() {
super.onAnimationFinish();
mControlCallbacks.mAnimationControl.finish(mAnimatingShown);
DisplayThread.getHandler().post(mFinishCallback);
}
private class InsetsPolicyAnimationControlCallbacks implements
InsetsAnimationControlCallbacks {
private InsetsAnimationControlImpl mAnimationControl = null;
private InsetsPolicyAnimationControlListener mListener;
InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) {
super();
mListener = listener;
}
private void controlAnimationUnchecked(int typesReady,
SparseArray<InsetsSourceControl> controls, boolean show) {
if (typesReady == 0) {
// nothing to animate.
return;
}
mAnimatingShown = show;
mAnimationControl = new InsetsAnimationControlImpl(controls,
mFocusedWin.getDisplayContent().getBounds(), getState(),
mListener, typesReady, this, mListener.getDurationMs(),
InsetsController.INTERPOLATOR, true,
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
}
/** Called on SurfaceAnimationThread lock without global WM lock held. */
@Override
public void scheduleApplyChangeInsets() {
InsetsState state = getState();
if (mAnimationControl.applyChangeInsets(state)) {
mAnimationControl.finish(mAnimatingShown);
}
}
@Override
public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
// Nothing's needed here. Finish steps is handled in the listener
// onAnimationFinished callback.
}
/**
* This method will return a state with fullscreen frame override. No need to make copy
* after getting state from this method.
* @return The client insets state with full display frame override.
*/
private InsetsState getState() {
// To animate the transient animation correctly, we need to let the state hold
// the full display frame.
InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(),
true);
overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds());
return overrideState;
}
/** Called on SurfaceAnimationThread lock without global WM lock held. */
@Override
public void applySurfaceParams(
final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
for (int i = params.length - 1; i >= 0; i--) {
SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i];
applyParams(t, surfaceParams, mTmpFloat9);
}
t.apply();
}
/** Called on SurfaceAnimationThread lock without global WM lock held. */
@Override
public void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
WindowInsetsAnimationCallback.InsetsAnimation animation,
WindowInsetsAnimationCallback.AnimationBounds bounds,
int layoutDuringAnimation) {
SurfaceAnimationThread.getHandler().post(() -> listener.onReady(controller, types));
}
}
}
private class TransientControlTarget implements InsetsControlTarget {
@Override