Merge "Use separate thread if app doesn't listen to animations" into rvc-dev
This commit is contained in:
@@ -18,6 +18,7 @@ package android.animation;
|
||||
|
||||
import android.annotation.CallSuper;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.os.Build;
|
||||
@@ -268,6 +269,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
*/
|
||||
private float mDurationScale = -1f;
|
||||
|
||||
/**
|
||||
* Animation handler used to schedule updates for this animation.
|
||||
*/
|
||||
private AnimationHandler mAnimationHandler;
|
||||
|
||||
/**
|
||||
* Public constants
|
||||
*/
|
||||
@@ -1684,6 +1690,15 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
* @hide
|
||||
*/
|
||||
public AnimationHandler getAnimationHandler() {
|
||||
return AnimationHandler.getInstance();
|
||||
return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the animation handler used to schedule updates for this animator or {@code null} to use
|
||||
* the default handler.
|
||||
* @hide
|
||||
*/
|
||||
public void setAnimationHandler(@Nullable AnimationHandler animationHandler) {
|
||||
mAnimationHandler = animationHandler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.view.InsetsController.LayoutInsetsDuringAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
|
||||
/**
|
||||
@@ -37,7 +36,7 @@ public interface InsetsAnimationControlCallbacks {
|
||||
void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation,
|
||||
Bounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);
|
||||
Bounds bounds);
|
||||
|
||||
/**
|
||||
* Schedule the apply by posting the animation callback.
|
||||
@@ -46,10 +45,10 @@ public interface InsetsAnimationControlCallbacks {
|
||||
|
||||
/**
|
||||
* Finish the final steps after the animation.
|
||||
* @param controller The controller used to control the animation.
|
||||
* @param runner The runner used to run the animation.
|
||||
* @param shown {@code true} if the insets are shown.
|
||||
*/
|
||||
void notifyFinished(InsetsAnimationControlImpl controller, boolean shown);
|
||||
void notifyFinished(InsetsAnimationControlRunner runner, boolean shown);
|
||||
|
||||
/**
|
||||
* Apply the new params to the surface.
|
||||
|
||||
@@ -31,9 +31,7 @@ import android.util.ArraySet;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.SparseSetArray;
|
||||
import android.view.InsetsController.LayoutInsetsDuringAnimation;
|
||||
import android.view.InsetsState.InternalInsetsSide;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
@@ -49,7 +47,8 @@ import java.util.ArrayList;
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public class InsetsAnimationControlImpl implements WindowInsetsAnimationController {
|
||||
public class InsetsAnimationControlImpl implements WindowInsetsAnimationController,
|
||||
InsetsAnimationControlRunner {
|
||||
|
||||
private final Rect mTmpFrame = new Rect();
|
||||
|
||||
@@ -84,8 +83,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
InsetsState state, WindowInsetsAnimationControlListener listener,
|
||||
@InsetsType int types,
|
||||
InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
|
||||
boolean fade, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
|
||||
@AnimationType int animationType) {
|
||||
boolean fade, @AnimationType int animationType) {
|
||||
mControls = controls;
|
||||
mListener = listener;
|
||||
mTypes = types;
|
||||
@@ -105,7 +103,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
mAnimation.setAlpha(getCurrentAlpha());
|
||||
mAnimationType = animationType;
|
||||
mController.startAnimation(this, listener, types, mAnimation,
|
||||
new Bounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
|
||||
new Bounds(mHiddenInsets, mShownInsets));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,11 +131,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
return mTypes;
|
||||
}
|
||||
|
||||
boolean controlsInternalType(@InternalInsetsType int type) {
|
||||
return InsetsState.toInternalType(mTypes).contains(type);
|
||||
}
|
||||
|
||||
@AnimationType int getAnimationType() {
|
||||
@Override
|
||||
public @AnimationType int getAnimationType() {
|
||||
return mAnimationType;
|
||||
}
|
||||
|
||||
@@ -205,7 +200,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
return mAnimation.getFraction();
|
||||
}
|
||||
|
||||
public void onCancelled() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (mFinished) {
|
||||
return;
|
||||
}
|
||||
@@ -217,7 +213,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
return mCancelled;
|
||||
}
|
||||
|
||||
WindowInsetsAnimation getAnimation() {
|
||||
@Override
|
||||
public WindowInsetsAnimation getAnimation() {
|
||||
return mAnimation;
|
||||
}
|
||||
|
||||
@@ -225,6 +222,10 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
return mListener;
|
||||
}
|
||||
|
||||
SparseArray<InsetsSourceControl> getControls() {
|
||||
return mControls;
|
||||
}
|
||||
|
||||
private Insets calculateInsets(InsetsState state, Rect frame,
|
||||
SparseArray<InsetsSourceControl> controls, boolean shown,
|
||||
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
|
||||
|
||||
56
core/java/android/view/InsetsAnimationControlRunner.java
Normal file
56
core/java/android/view/InsetsAnimationControlRunner.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 android.view.InsetsController.AnimationType;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
|
||||
/**
|
||||
* Interface representing a runner for an insets animation.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface InsetsAnimationControlRunner {
|
||||
|
||||
/**
|
||||
* @return The {@link InsetsType} the animation of this runner is controlling.
|
||||
*/
|
||||
@InsetsType int getTypes();
|
||||
|
||||
/**
|
||||
* Cancels the animation.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* @return The animation this runner is running.
|
||||
*/
|
||||
WindowInsetsAnimation getAnimation();
|
||||
|
||||
/**
|
||||
* @return Whether {@link #getTypes()} maps to a specific {@link InternalInsetsType}.
|
||||
*/
|
||||
default boolean controlsInternalType(@InternalInsetsType int type) {
|
||||
return InsetsState.toInternalType(getTypes()).contains(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The animation type this runner is running.
|
||||
*/
|
||||
@AnimationType int getAnimationType();
|
||||
}
|
||||
70
core/java/android/view/InsetsAnimationThread.java
Normal file
70
core/java/android/view/InsetsAnimationThread.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Trace;
|
||||
|
||||
/**
|
||||
* Thread to be used for inset animations to be running off the main thread.
|
||||
* @hide
|
||||
*/
|
||||
public class InsetsAnimationThread extends HandlerThread {
|
||||
|
||||
private static InsetsAnimationThread sInstance;
|
||||
private static Handler sHandler;
|
||||
|
||||
private InsetsAnimationThread() {
|
||||
// TODO: Should this use higher priority?
|
||||
super("InsetsAnimations");
|
||||
}
|
||||
|
||||
private static void ensureThreadLocked() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new InsetsAnimationThread();
|
||||
sInstance.start();
|
||||
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_VIEW);
|
||||
sHandler = new Handler(sInstance.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
synchronized (InsetsAnimationThread.class) {
|
||||
if (sInstance == null) {
|
||||
return;
|
||||
}
|
||||
sInstance.getLooper().quitSafely();
|
||||
sInstance = null;
|
||||
sHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static InsetsAnimationThread get() {
|
||||
synchronized (InsetsAnimationThread.class) {
|
||||
ensureThreadLocked();
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public static Handler getHandler() {
|
||||
synchronized (InsetsAnimationThread.class) {
|
||||
ensureThreadLocked();
|
||||
return sHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
130
core/java/android/view/InsetsAnimationThreadControlRunner.java
Normal file
130
core/java/android/view/InsetsAnimationThreadControlRunner.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.SyncRtSurfaceTransactionApplier.applyParams;
|
||||
|
||||
import android.annotation.UiThread;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InsetsController.AnimationType;
|
||||
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
/**
|
||||
* Insets animation runner that uses {@link InsetsAnimationThread} to run the animation off from the
|
||||
* main thread.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class InsetsAnimationThreadControlRunner implements InsetsAnimationControlRunner {
|
||||
|
||||
private final InsetsAnimationControlImpl mControl;
|
||||
private final InsetsAnimationControlCallbacks mOuterCallbacks;
|
||||
private final Handler mMainThreadHandler;
|
||||
private final InsetsState mState = new InsetsState();
|
||||
private final InsetsAnimationControlCallbacks mCallbacks =
|
||||
new InsetsAnimationControlCallbacks() {
|
||||
|
||||
private final float[] mTmpFloat9 = new float[9];
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation, Bounds bounds) {
|
||||
// Animation will be started in constructor already.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleApplyChangeInsets() {
|
||||
mControl.applyChangeInsets(mState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
|
||||
releaseControls(mControl.getControls());
|
||||
mMainThreadHandler.post(() ->
|
||||
mOuterCallbacks.notifyFinished(InsetsAnimationThreadControlRunner.this, shown));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySurfaceParams(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();
|
||||
t.close();
|
||||
}
|
||||
};
|
||||
|
||||
@UiThread
|
||||
public InsetsAnimationThreadControlRunner(SparseArray<InsetsSourceControl> controls, Rect frame,
|
||||
InsetsState state, WindowInsetsAnimationControlListener listener,
|
||||
@InsetsType int types,
|
||||
InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
|
||||
boolean fade, @AnimationType int animationType, Handler mainThreadHandler) {
|
||||
mMainThreadHandler = mainThreadHandler;
|
||||
mOuterCallbacks = controller;
|
||||
mControl = new InsetsAnimationControlImpl(copyControls(controls), frame, state, listener,
|
||||
types, mCallbacks, durationMs, interpolator, fade, animationType);
|
||||
InsetsAnimationThread.getHandler().post(() -> listener.onReady(mControl, types));
|
||||
}
|
||||
|
||||
private void releaseControls(SparseArray<InsetsSourceControl> controls) {
|
||||
for (int i = controls.size() - 1; i >= 0; i--) {
|
||||
controls.valueAt(i).release(SurfaceControl::release);
|
||||
}
|
||||
}
|
||||
|
||||
private SparseArray<InsetsSourceControl> copyControls(
|
||||
SparseArray<InsetsSourceControl> controls) {
|
||||
SparseArray<InsetsSourceControl> copy = new SparseArray<>(controls.size());
|
||||
for (int i = 0; i < controls.size(); i++) {
|
||||
copy.append(controls.keyAt(i), new InsetsSourceControl(controls.valueAt(i)));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public int getTypes() {
|
||||
return mControl.getTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void cancel() {
|
||||
InsetsAnimationThread.getHandler().post(mControl::cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public WindowInsetsAnimation getAnimation() {
|
||||
return mControl.getAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnimationType() {
|
||||
return mControl.getAnimationType();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import static android.view.WindowInsets.Type.ime;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
|
||||
|
||||
import android.animation.AnimationHandler;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -53,6 +54,7 @@ import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -167,10 +169,22 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
|
||||
private WindowInsetsAnimationController mController;
|
||||
private ObjectAnimator mAnimator;
|
||||
protected boolean mShow;
|
||||
private final boolean mShow;
|
||||
private final boolean mUseSfVsync;
|
||||
|
||||
public InternalAnimationControlListener(boolean show) {
|
||||
private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
|
||||
new ThreadLocal<AnimationHandler>() {
|
||||
@Override
|
||||
protected AnimationHandler initialValue() {
|
||||
AnimationHandler handler = new AnimationHandler();
|
||||
handler.setProvider(new SfVsyncFrameCallbackProvider());
|
||||
return handler;
|
||||
}
|
||||
};
|
||||
|
||||
public InternalAnimationControlListener(boolean show, boolean useSfVsync) {
|
||||
mShow = show;
|
||||
mUseSfVsync = useSfVsync;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,6 +207,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
onAnimationFinish();
|
||||
}
|
||||
});
|
||||
if (mUseSfVsync) {
|
||||
mAnimator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
|
||||
}
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
@@ -228,12 +245,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
*/
|
||||
private static class RunningAnimation {
|
||||
|
||||
RunningAnimation(InsetsAnimationControlImpl control, int type) {
|
||||
this.control = control;
|
||||
RunningAnimation(InsetsAnimationControlRunner runner, int type) {
|
||||
this.runner = runner;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
final InsetsAnimationControlImpl control;
|
||||
final InsetsAnimationControlRunner runner;
|
||||
final @AnimationType int type;
|
||||
|
||||
/**
|
||||
@@ -252,7 +269,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener,
|
||||
long durationMs, Interpolator interpolator, @AnimationType int animationType,
|
||||
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
|
||||
CancellationSignal cancellationSignal) {
|
||||
CancellationSignal cancellationSignal, boolean useInsetsAnimationThread) {
|
||||
this.types = types;
|
||||
this.listener = listener;
|
||||
this.durationMs = durationMs;
|
||||
@@ -260,6 +277,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
this.animationType = animationType;
|
||||
this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
|
||||
this.cancellationSignal = cancellationSignal;
|
||||
this.useInsetsAnimationThread = useInsetsAnimationThread;
|
||||
}
|
||||
|
||||
final @InsetsType int types;
|
||||
@@ -269,6 +287,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
final @AnimationType int animationType;
|
||||
final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation;
|
||||
final CancellationSignal cancellationSignal;
|
||||
final boolean useInsetsAnimationThread;
|
||||
}
|
||||
|
||||
private final String TAG = "InsetsControllerImpl";
|
||||
@@ -347,15 +366,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
InsetsState state = new InsetsState(mState, true /* copySources */);
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
RunningAnimation runningAnimation = mRunningAnimations.get(i);
|
||||
InsetsAnimationControlImpl control = runningAnimation.control;
|
||||
InsetsAnimationControlRunner runner = runningAnimation.runner;
|
||||
if (runner instanceof InsetsAnimationControlImpl) {
|
||||
InsetsAnimationControlImpl control = (InsetsAnimationControlImpl) runner;
|
||||
|
||||
// Keep track of running animation to be dispatched. Aggregate it here such that if
|
||||
// it gets finished within applyChangeInsets we still dispatch it to onProgress.
|
||||
if (runningAnimation.startDispatched) {
|
||||
mTmpRunningAnims.add(control.getAnimation());
|
||||
}
|
||||
if (control.applyChangeInsets(state)) {
|
||||
mTmpFinishedControls.add(control);
|
||||
// Keep track of running animation to be dispatched. Aggregate it here such that
|
||||
// if it gets finished within applyChangeInsets we still dispatch it to
|
||||
// onProgress.
|
||||
if (runningAnimation.startDispatched) {
|
||||
mTmpRunningAnims.add(control.getAnimation());
|
||||
}
|
||||
|
||||
if (control.applyChangeInsets(state)) {
|
||||
mTmpFinishedControls.add(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +523,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
pendingRequest.listener, mFrame,
|
||||
true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
|
||||
false /* fade */, pendingRequest.animationType,
|
||||
pendingRequest.layoutInsetsDuringAnimation);
|
||||
pendingRequest.layoutInsetsDuringAnimation,
|
||||
pendingRequest.useInsetsAnimationThread);
|
||||
pendingRequest.cancellationSignal.setOnCancelListener(cancellationSignal::cancel);
|
||||
return;
|
||||
}
|
||||
@@ -563,7 +588,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
return cancellationSignal;
|
||||
}
|
||||
return controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator,
|
||||
false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types));
|
||||
false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types),
|
||||
false /* useInsetsAnimationThread */);
|
||||
}
|
||||
|
||||
private boolean checkDisplayFramesForControlling() {
|
||||
@@ -577,7 +603,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
|
||||
long durationMs, Interpolator interpolator, boolean fade,
|
||||
@AnimationType int animationType,
|
||||
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
|
||||
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
|
||||
boolean useInsetsAnimationThread) {
|
||||
CancellationSignal cancellationSignal = new CancellationSignal();
|
||||
if (types == 0) {
|
||||
// nothing to animate.
|
||||
@@ -600,7 +627,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
abortPendingImeControlRequest();
|
||||
final PendingControlRequest request = new PendingControlRequest(types,
|
||||
listener, durationMs,
|
||||
interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal);
|
||||
interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal,
|
||||
useInsetsAnimationThread);
|
||||
mPendingImeControlRequest = request;
|
||||
mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
|
||||
cancellationSignal.setOnCancelListener(() -> {
|
||||
@@ -617,11 +645,21 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
return cancellationSignal;
|
||||
}
|
||||
|
||||
final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls,
|
||||
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
|
||||
layoutInsetsDuringAnimation, animationType);
|
||||
mRunningAnimations.add(new RunningAnimation(controller, animationType));
|
||||
cancellationSignal.setOnCancelListener(controller::onCancelled);
|
||||
|
||||
final InsetsAnimationControlRunner runner = useInsetsAnimationThread
|
||||
? new InsetsAnimationThreadControlRunner(controls,
|
||||
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
|
||||
animationType, mViewRoot.mHandler)
|
||||
: new InsetsAnimationControlImpl(controls,
|
||||
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
|
||||
animationType);
|
||||
mRunningAnimations.add(new RunningAnimation(runner, animationType));
|
||||
cancellationSignal.setOnCancelListener(runner::cancel);
|
||||
if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
|
||||
showDirectly(types);
|
||||
} else {
|
||||
hideDirectly(types, false /* animationFinished */, animationType);
|
||||
}
|
||||
return cancellationSignal;
|
||||
}
|
||||
|
||||
@@ -705,7 +743,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
|
||||
private void cancelExistingControllers(@InsetsType int types) {
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
|
||||
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
|
||||
if ((control.getTypes() & types) != 0) {
|
||||
cancelAnimation(control, true /* invokeCallback */);
|
||||
}
|
||||
@@ -725,13 +763,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
|
||||
@VisibleForTesting
|
||||
@Override
|
||||
public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
|
||||
cancelAnimation(controller, false /* invokeCallback */);
|
||||
public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
|
||||
cancelAnimation(runner, false /* invokeCallback */);
|
||||
if (shown) {
|
||||
showDirectly(controller.getTypes());
|
||||
showDirectly(runner.getTypes());
|
||||
} else {
|
||||
hideDirectly(controller.getTypes(), true /* animationFinished */,
|
||||
controller.getAnimationType());
|
||||
hideDirectly(runner.getTypes(), true /* animationFinished */,
|
||||
runner.getAnimationType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,7 +794,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
|
||||
void notifyControlRevoked(InsetsSourceConsumer consumer) {
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
|
||||
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
|
||||
if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
|
||||
cancelAnimation(control, true /* invokeCallback */);
|
||||
}
|
||||
@@ -766,12 +804,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelAnimation(InsetsAnimationControlImpl control, boolean invokeCallback) {
|
||||
private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
|
||||
if (invokeCallback) {
|
||||
control.onCancelled();
|
||||
control.cancel();
|
||||
}
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
if (mRunningAnimations.get(i).control == control) {
|
||||
if (mRunningAnimations.get(i).runner == control) {
|
||||
mRunningAnimations.remove(i);
|
||||
break;
|
||||
}
|
||||
@@ -844,7 +882,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
@VisibleForTesting
|
||||
public @AnimationType int getAnimationType(@InternalInsetsType int type) {
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
|
||||
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
|
||||
if (control.controlsInternalType(type)) {
|
||||
return mRunningAnimations.get(i).type;
|
||||
}
|
||||
@@ -878,15 +916,24 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
return;
|
||||
}
|
||||
|
||||
boolean useInsetsAnimationThread = canUseInsetsAnimationThread();
|
||||
final InternalAnimationControlListener listener =
|
||||
new InternalAnimationControlListener(show);
|
||||
new InternalAnimationControlListener(show, useInsetsAnimationThread);
|
||||
// Show/hide animations always need to be relative to the display frame, in order that shown
|
||||
// and hidden state insets are correct.
|
||||
controlAnimationUnchecked(
|
||||
types, listener, mState.getDisplayFrame(), fromIme, listener.getDurationMs(),
|
||||
INTERPOLATOR, true /* fade */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
|
||||
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
|
||||
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
|
||||
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
|
||||
useInsetsAnimationThread);
|
||||
}
|
||||
|
||||
private boolean canUseInsetsAnimationThread() {
|
||||
if (mViewRoot.mView == null) {
|
||||
return true;
|
||||
}
|
||||
return !mViewRoot.mView.hasWindowInsetsAnimationCallback();
|
||||
}
|
||||
|
||||
private void hideDirectly(
|
||||
@@ -921,13 +968,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
@Override
|
||||
public void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation, Bounds bounds, int layoutDuringAnimation) {
|
||||
if (layoutDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
|
||||
showDirectly(types);
|
||||
} else {
|
||||
hideDirectly(types, false /* animationFinished */, controller.getAnimationType());
|
||||
}
|
||||
|
||||
WindowInsetsAnimation animation, Bounds bounds) {
|
||||
if (mViewRoot.mView == null) {
|
||||
return;
|
||||
}
|
||||
@@ -941,7 +982,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
}
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
RunningAnimation runningAnimation = mRunningAnimations.get(i);
|
||||
if (runningAnimation.control == controller) {
|
||||
if (runningAnimation.runner == controller) {
|
||||
runningAnimation.startDispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public class InsetsSourceConsumer {
|
||||
}
|
||||
}
|
||||
if (lastControl != null) {
|
||||
lastControl.release(mController);
|
||||
lastControl.release(mController::releaseSurfaceControlFromRt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Represents a parcelable object to allow controlling a single {@link InsetsSource}.
|
||||
* @hide
|
||||
@@ -94,9 +96,9 @@ public class InsetsSourceControl implements Parcelable {
|
||||
dest.writeParcelable(mSurfacePosition, 0 /* flags*/);
|
||||
}
|
||||
|
||||
public void release(InsetsController controller) {
|
||||
public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) {
|
||||
if (mLeash != null) {
|
||||
controller.releaseSurfaceControlFromRt(mLeash);
|
||||
surfaceReleaseConsumer.accept(mLeash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11226,6 +11226,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
getListenerInfo().mWindowInsetsAnimationCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
|
||||
* or view tree of the sub-hierarchy {@code false} otherwise.
|
||||
* @hide
|
||||
*/
|
||||
public boolean hasWindowInsetsAnimationCallback() {
|
||||
return getListenerInfo().mWindowInsetsAnimationCallback != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
|
||||
* when Window Insets animation is being prepared.
|
||||
|
||||
@@ -7258,6 +7258,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
: DISPATCH_MODE_CONTINUE_ON_SUBTREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public boolean hasWindowInsetsAnimationCallback() {
|
||||
if (super.hasWindowInsetsAnimationCallback()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we are root-level content view that fits insets, we imitate consuming behavior, so
|
||||
// no child will retrieve window insets animation callback.
|
||||
// See dispatchWindowInsetsAnimationPrepare.
|
||||
boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
|
||||
|| isFrameworkOptionalFitsSystemWindows();
|
||||
if (isOptionalFitSystemWindows && mAttachInfo != null
|
||||
&& mAttachInfo.mContentOnApplyWindowInsetsListener != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (getChildAt(i).hasWindowInsetsAnimationCallback()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowInsetsAnimationPrepare(
|
||||
@NonNull WindowInsetsAnimation animation) {
|
||||
|
||||
@@ -504,6 +504,7 @@ public final class WindowManagerGlobal {
|
||||
}
|
||||
|
||||
void doRemoveView(ViewRootImpl root) {
|
||||
boolean allViewsRemoved;
|
||||
synchronized (mLock) {
|
||||
final int index = mRoots.indexOf(root);
|
||||
if (index >= 0) {
|
||||
@@ -512,10 +513,17 @@ public final class WindowManagerGlobal {
|
||||
final View view = mViews.remove(index);
|
||||
mDyingViews.remove(view);
|
||||
}
|
||||
allViewsRemoved = mRoots.isEmpty();
|
||||
}
|
||||
if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
|
||||
doTrimForeground();
|
||||
}
|
||||
|
||||
// If we don't have any views anymore in our process, we no longer need the
|
||||
// InsetsAnimationThread to save some resources.
|
||||
if (allViewsRemoved) {
|
||||
InsetsAnimationThread.release();
|
||||
}
|
||||
}
|
||||
|
||||
private int findViewLocked(View view, boolean required) {
|
||||
|
||||
@@ -123,7 +123,7 @@ public class InsetsAnimationControlImplTest {
|
||||
mController = new InsetsAnimationControlImpl(controls,
|
||||
new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
|
||||
mMockController, 10 /* durationMs */, new LinearInterpolator(),
|
||||
false /* fade */, LAYOUT_INSETS_DURING_ANIMATION_SHOWN, 0 /* animationType */);
|
||||
false /* fade */, 0 /* animationType */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,7 +182,7 @@ public class InsetsAnimationControlImplTest {
|
||||
|
||||
@Test
|
||||
public void testCancelled() {
|
||||
mController.onCancelled();
|
||||
mController.cancel();
|
||||
try {
|
||||
mController.setInsetsAndAlpha(Insets.NONE, 1f /*alpha */, 0f /* fraction */);
|
||||
fail("Expected exception to be thrown");
|
||||
|
||||
@@ -31,6 +31,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -47,6 +48,7 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.CancellationSignal;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
|
||||
@@ -169,11 +171,8 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testControlsChanged() {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { control });
|
||||
assertEquals(mLeash,
|
||||
mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl().getLeash());
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
assertNotNull(mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl().getLeash());
|
||||
mController.addOnControllableInsetsChangedListener(
|
||||
((controller, typeMask) -> assertEquals(statusBars(), typeMask)));
|
||||
}
|
||||
@@ -183,9 +182,7 @@ public class InsetsControllerTest {
|
||||
OnControllableInsetsChangedListener listener
|
||||
= mock(OnControllableInsetsChangedListener.class);
|
||||
mController.addOnControllableInsetsChangedListener(listener);
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { control });
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
mController.onControlsChanged(new InsetsSourceControl[0]);
|
||||
assertNull(mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl());
|
||||
InOrder inOrder = Mockito.inOrder(listener);
|
||||
@@ -197,9 +194,7 @@ public class InsetsControllerTest {
|
||||
@Test
|
||||
public void testControlsRevoked_duringAnim() {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { control });
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
|
||||
WindowInsetsAnimationControlListener mockListener =
|
||||
mock(WindowInsetsAnimationControlListener.class);
|
||||
@@ -262,11 +257,8 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testApplyImeVisibility() {
|
||||
final InsetsSourceControl ime = new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
|
||||
|
||||
InsetsSourceControl[] controls = new InsetsSourceControl[3];
|
||||
controls[0] = ime;
|
||||
mController.onControlsChanged(controls);
|
||||
InsetsSourceControl ime = createControl(ITYPE_IME);
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { ime });
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
|
||||
mController.applyImeVisibility(true);
|
||||
@@ -429,9 +421,7 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testRestoreStartsAnimation() {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[]{control});
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
mController.hide(Type.statusBars());
|
||||
@@ -448,7 +438,7 @@ public class InsetsControllerTest {
|
||||
assertTrue(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
|
||||
|
||||
// Gaining control
|
||||
mController.onControlsChanged(new InsetsSourceControl[]{control});
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
|
||||
mController.cancelExistingAnimation();
|
||||
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
|
||||
@@ -459,8 +449,6 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testStartImeAnimationAfterGettingControl() {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
|
||||
@@ -471,7 +459,7 @@ public class InsetsControllerTest {
|
||||
mController.show(ime(), true /* fromIme */);
|
||||
|
||||
// Gaining control shortly after
|
||||
mController.onControlsChanged(new InsetsSourceControl[]{control});
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
|
||||
|
||||
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_IME));
|
||||
mController.cancelExistingAnimation();
|
||||
@@ -483,16 +471,13 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testStartImeAnimationAfterGettingControl_imeLater() {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
|
||||
mController.show(ime());
|
||||
assertFalse(mController.getState().getSource(ITYPE_IME).isVisible());
|
||||
|
||||
// Gaining control shortly after
|
||||
mController.onControlsChanged(new InsetsSourceControl[]{control});
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
|
||||
|
||||
// Pretend IME is calling
|
||||
mController.show(ime(), true /* fromIme */);
|
||||
@@ -507,9 +492,7 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testAnimationEndState_controller() throws Exception {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { control });
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
WindowInsetsAnimationControlListener mockListener =
|
||||
@@ -535,9 +518,7 @@ public class InsetsControllerTest {
|
||||
|
||||
@Test
|
||||
public void testCancellation_afterGainingControl() throws Exception {
|
||||
InsetsSourceControl control =
|
||||
new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
|
||||
mController.onControlsChanged(new InsetsSourceControl[] { control });
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
WindowInsetsAnimationControlListener mockListener =
|
||||
@@ -655,12 +636,23 @@ public class InsetsControllerTest {
|
||||
latch.await();
|
||||
}
|
||||
|
||||
private InsetsSourceControl createControl(@InternalInsetsType int type) {
|
||||
|
||||
// Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will
|
||||
// attempt to release mLeash directly.
|
||||
SurfaceControl copy = new SurfaceControl();
|
||||
copy.copyFrom(mLeash);
|
||||
return new InsetsSourceControl(type, copy, new Point());
|
||||
}
|
||||
|
||||
private InsetsSourceControl[] createSingletonControl(@InternalInsetsType int type) {
|
||||
return new InsetsSourceControl[] { createControl(type) };
|
||||
}
|
||||
|
||||
private InsetsSourceControl[] prepareControls() {
|
||||
final InsetsSourceControl navBar = new InsetsSourceControl(ITYPE_NAVIGATION_BAR, mLeash,
|
||||
new Point());
|
||||
final InsetsSourceControl statusBar = new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash,
|
||||
new Point());
|
||||
final InsetsSourceControl ime = new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
|
||||
final InsetsSourceControl navBar = createControl(ITYPE_NAVIGATION_BAR);
|
||||
final InsetsSourceControl statusBar = createControl(ITYPE_STATUS_BAR);
|
||||
final InsetsSourceControl ime = createControl(ITYPE_IME);
|
||||
|
||||
InsetsSourceControl[] controls = new InsetsSourceControl[3];
|
||||
controls[0] = navBar;
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.util.IntArray;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InsetsAnimationControlCallbacks;
|
||||
import android.view.InsetsAnimationControlImpl;
|
||||
import android.view.InsetsAnimationControlRunner;
|
||||
import android.view.InsetsController;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.InsetsState;
|
||||
@@ -44,6 +45,7 @@ import android.view.SurfaceControl;
|
||||
import android.view.SyncRtSurfaceTransactionApplier;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.WindowInsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.WindowInsetsAnimationControlListener;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -327,7 +329,7 @@ class InsetsPolicy {
|
||||
InsetsPolicyAnimationControlCallbacks mControlCallbacks;
|
||||
|
||||
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback) {
|
||||
super(show);
|
||||
super(show, true /* useSfVsync */);
|
||||
mFinishCallback = finishCallback;
|
||||
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
|
||||
}
|
||||
@@ -360,8 +362,6 @@ class InsetsPolicy {
|
||||
mFocusedWin.getDisplayContent().getBounds(), getState(),
|
||||
mListener, typesReady, this, mListener.getDurationMs(),
|
||||
InsetsController.INTERPOLATOR, true,
|
||||
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
|
||||
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
|
||||
show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
|
||||
SurfaceAnimationThread.getHandler().post(
|
||||
() -> mListener.onReady(mAnimationControl, typesReady));
|
||||
@@ -377,7 +377,7 @@ class InsetsPolicy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
|
||||
public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
|
||||
// Nothing's needed here. Finish steps is handled in the listener
|
||||
// onAnimationFinished callback.
|
||||
}
|
||||
@@ -406,14 +406,14 @@ class InsetsPolicy {
|
||||
applyParams(t, surfaceParams, mTmpFloat9);
|
||||
}
|
||||
t.apply();
|
||||
t.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation,
|
||||
WindowInsetsAnimation.Bounds bounds,
|
||||
int layoutDuringAnimation) {
|
||||
Bounds bounds) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user