Merge "Ensure that we use SF Vsync Choreographer for the PiP transition." into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e1e0db8ca9
@@ -1469,24 +1469,21 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.addOneShotCommitCallback(this);
|
||||
getAnimationHandler().addOneShotCommitCallback(this);
|
||||
}
|
||||
|
||||
private void removeAnimationCallback() {
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.removeCallback(this);
|
||||
getAnimationHandler().removeCallback(this);
|
||||
}
|
||||
|
||||
private void addAnimationCallback(long delay) {
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.addAnimationFrameCallback(this, delay);
|
||||
getAnimationHandler().addAnimationFrameCallback(this, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1643,4 +1640,12 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
public void setAllowRunningAsynchronously(boolean mayRunAsync) {
|
||||
// It is up to subclasses to support this, if they can.
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link AnimationHandler} that will be used to schedule updates for this animator.
|
||||
* @hide
|
||||
*/
|
||||
public AnimationHandler getAnimationHandler() {
|
||||
return AnimationHandler.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 com.android.internal.graphics;
|
||||
|
||||
import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
|
||||
import android.view.Choreographer;
|
||||
|
||||
/**
|
||||
* Provider of timing pulse that uses SurfaceFlinger Vsync Choreographer for frame callbacks.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider {
|
||||
|
||||
private final Choreographer mChoreographer = Choreographer.getSfInstance();
|
||||
|
||||
@Override
|
||||
public void postFrameCallback(Choreographer.FrameCallback callback) {
|
||||
mChoreographer.postFrameCallback(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCommitCallback(Runnable runnable) {
|
||||
mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrameTime() {
|
||||
return mChoreographer.getFrameTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrameDelay() {
|
||||
return Choreographer.getFrameDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrameDelay(long delay) {
|
||||
Choreographer.setFrameDelay(delay);
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,15 @@ import static android.view.WindowManager.INPUT_CONSUMER_PIP;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.BatchedInputEventReceiver;
|
||||
import android.view.Choreographer;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
@@ -52,12 +55,13 @@ public class InputConsumerController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Input handler used for the PiP input consumer.
|
||||
* Input handler used for the PiP input consumer. Input events are batched and consumed with the
|
||||
* SurfaceFlinger vsync.
|
||||
*/
|
||||
private final class PipInputEventReceiver extends InputEventReceiver {
|
||||
private final class PipInputEventReceiver extends BatchedInputEventReceiver {
|
||||
|
||||
public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
|
||||
super(inputChannel, looper);
|
||||
super(inputChannel, looper, Choreographer.getSfInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -573,13 +573,11 @@ public class PipMenuActivity extends Activity {
|
||||
}
|
||||
|
||||
private void cancelDelayedFinish() {
|
||||
View v = getWindow().getDecorView();
|
||||
v.removeCallbacks(mFinishRunnable);
|
||||
mHandler.removeCallbacks(mFinishRunnable);
|
||||
}
|
||||
|
||||
private void repostDelayedFinish(long delay) {
|
||||
View v = getWindow().getDecorView();
|
||||
v.removeCallbacks(mFinishRunnable);
|
||||
v.postDelayed(mFinishRunnable, delay);
|
||||
mHandler.removeCallbacks(mFinishRunnable);
|
||||
mHandler.postDelayed(mFinishRunnable, delay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
|
||||
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
|
||||
|
||||
import android.animation.AnimationHandler;
|
||||
import android.animation.Animator;
|
||||
import android.animation.Animator.AnimatorListener;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -36,14 +37,15 @@ import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.Choreographer;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.policy.PipSnapAlgorithm;
|
||||
import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
|
||||
import com.android.systemui.recents.misc.ForegroundThread;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.statusbar.FlingAnimationUtils;
|
||||
|
||||
@@ -52,7 +54,7 @@ import java.io.PrintWriter;
|
||||
/**
|
||||
* A helper to animate and manipulate the PiP.
|
||||
*/
|
||||
public class PipMotionHelper {
|
||||
public class PipMotionHelper implements Handler.Callback {
|
||||
|
||||
private static final String TAG = "PipMotionHelper";
|
||||
private static final boolean DEBUG = false;
|
||||
@@ -74,38 +76,34 @@ public class PipMotionHelper {
|
||||
// The fraction of the stack height that the user has to drag offscreen to dismiss the PiP
|
||||
private static final float DISMISS_OFFSCREEN_FRACTION = 0.3f;
|
||||
|
||||
private static final int MSG_RESIZE_IMMEDIATE = 1;
|
||||
private static final int MSG_RESIZE_ANIMATE = 2;
|
||||
|
||||
private Context mContext;
|
||||
private IActivityManager mActivityManager;
|
||||
private SurfaceFlingerVsyncChoreographer mVsyncChoreographer;
|
||||
private Handler mHandler;
|
||||
|
||||
private PipMenuActivityController mMenuController;
|
||||
private PipSnapAlgorithm mSnapAlgorithm;
|
||||
private FlingAnimationUtils mFlingAnimationUtils;
|
||||
private AnimationHandler mAnimationHandler;
|
||||
|
||||
private final Rect mBounds = new Rect();
|
||||
private final Rect mStableInsets = new Rect();
|
||||
|
||||
private ValueAnimator mBoundsAnimator = null;
|
||||
private ValueAnimator.AnimatorUpdateListener mUpdateBoundsListener =
|
||||
new AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mBounds.set((Rect) animation.getAnimatedValue());
|
||||
}
|
||||
};
|
||||
|
||||
public PipMotionHelper(Context context, IActivityManager activityManager,
|
||||
PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm,
|
||||
FlingAnimationUtils flingAnimationUtils) {
|
||||
mContext = context;
|
||||
mHandler = BackgroundThread.getHandler();
|
||||
mHandler = new Handler(ForegroundThread.get().getLooper(), this);
|
||||
mActivityManager = activityManager;
|
||||
mMenuController = menuController;
|
||||
mSnapAlgorithm = snapAlgorithm;
|
||||
mFlingAnimationUtils = flingAnimationUtils;
|
||||
mVsyncChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, mContext.getDisplay(),
|
||||
Choreographer.getInstance());
|
||||
mAnimationHandler = new AnimationHandler();
|
||||
mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
|
||||
onConfigurationChanged();
|
||||
}
|
||||
|
||||
@@ -252,8 +250,7 @@ public class PipMotionHelper {
|
||||
Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds,
|
||||
0 /* velocityX */, velocityY);
|
||||
if (!mBounds.equals(toBounds)) {
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN,
|
||||
mUpdateBoundsListener);
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN);
|
||||
mFlingAnimationUtils.apply(mBoundsAnimator, 0,
|
||||
distanceBetweenRectOffsets(mBounds, toBounds),
|
||||
velocityY);
|
||||
@@ -271,7 +268,7 @@ public class PipMotionHelper {
|
||||
Rect toBounds = getClosestMinimizedBounds(mBounds, movementBounds);
|
||||
if (!mBounds.equals(toBounds)) {
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
|
||||
MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdateBoundsListener);
|
||||
MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN);
|
||||
if (updateListener != null) {
|
||||
mBoundsAnimator.addUpdateListener(updateListener);
|
||||
}
|
||||
@@ -289,8 +286,7 @@ public class PipMotionHelper {
|
||||
Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds,
|
||||
velocityX, velocityY);
|
||||
if (!mBounds.equals(toBounds)) {
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN,
|
||||
mUpdateBoundsListener);
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN);
|
||||
mFlingAnimationUtils.apply(mBoundsAnimator, 0,
|
||||
distanceBetweenRectOffsets(mBounds, toBounds),
|
||||
velocity);
|
||||
@@ -314,7 +310,7 @@ public class PipMotionHelper {
|
||||
Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds);
|
||||
if (!mBounds.equals(toBounds)) {
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, SNAP_STACK_DURATION,
|
||||
FAST_OUT_SLOW_IN, mUpdateBoundsListener);
|
||||
FAST_OUT_SLOW_IN);
|
||||
if (updateListener != null) {
|
||||
mBoundsAnimator.addUpdateListener(updateListener);
|
||||
}
|
||||
@@ -379,7 +375,7 @@ public class PipMotionHelper {
|
||||
Rect toBounds = new Rect(pipBounds);
|
||||
toBounds.offsetTo(p.x, p.y);
|
||||
mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, DRAG_TO_DISMISS_STACK_DURATION,
|
||||
FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
|
||||
FAST_OUT_LINEAR_IN);
|
||||
mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
@@ -411,16 +407,20 @@ public class PipMotionHelper {
|
||||
* Creates an animation to move the PiP to give given {@param toBounds}.
|
||||
*/
|
||||
private ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds, int duration,
|
||||
Interpolator interpolator, ValueAnimator.AnimatorUpdateListener updateListener) {
|
||||
ValueAnimator anim = ValueAnimator.ofObject(RECT_EVALUATOR, fromBounds, toBounds);
|
||||
Interpolator interpolator) {
|
||||
ValueAnimator anim = new ValueAnimator() {
|
||||
@Override
|
||||
public AnimationHandler getAnimationHandler() {
|
||||
return mAnimationHandler;
|
||||
}
|
||||
};
|
||||
anim.setObjectValues(fromBounds, toBounds);
|
||||
anim.setEvaluator(RECT_EVALUATOR);
|
||||
anim.setDuration(duration);
|
||||
anim.setInterpolator(interpolator);
|
||||
anim.addUpdateListener((ValueAnimator animation) -> {
|
||||
resizePipUnchecked((Rect) animation.getAnimatedValue());
|
||||
});
|
||||
if (updateListener != null) {
|
||||
anim.addUpdateListener(updateListener);
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
@@ -433,14 +433,9 @@ public class PipMotionHelper {
|
||||
+ " callers=\n" + Debug.getCallers(5, " "));
|
||||
}
|
||||
if (!toBounds.equals(mBounds)) {
|
||||
mVsyncChoreographer.scheduleAtSfVsync(() -> {
|
||||
try {
|
||||
mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
|
||||
mBounds.set(toBounds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not resize pinned stack to bounds: " + toBounds, e);
|
||||
}
|
||||
});
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = toBounds;
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_RESIZE_IMMEDIATE, args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,23 +448,10 @@ public class PipMotionHelper {
|
||||
+ " duration=" + duration + " callers=\n" + Debug.getCallers(5, " "));
|
||||
}
|
||||
if (!toBounds.equals(mBounds)) {
|
||||
mHandler.post(() -> {
|
||||
try {
|
||||
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
|
||||
if (stackInfo == null) {
|
||||
// In the case where we've already re-expanded or dismissed the PiP, then
|
||||
// just skip the resize
|
||||
return;
|
||||
}
|
||||
|
||||
mActivityManager.resizeStack(PINNED_STACK_ID, toBounds,
|
||||
false /* allowResizeInDockedMode */, true /* preserveWindows */,
|
||||
true /* animate */, duration);
|
||||
mBounds.set(toBounds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e);
|
||||
}
|
||||
});
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = toBounds;
|
||||
args.argi1 = duration;
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,6 +506,50 @@ public class PipMotionHelper {
|
||||
return PointF.length(r1.left - r2.left, r1.top - r2.top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles messages to be processed on the background thread.
|
||||
*/
|
||||
public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_RESIZE_IMMEDIATE: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Rect toBounds = (Rect) args.arg1;
|
||||
try {
|
||||
mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
|
||||
mBounds.set(toBounds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not resize pinned stack to bounds: " + toBounds, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case MSG_RESIZE_ANIMATE: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Rect toBounds = (Rect) args.arg1;
|
||||
int duration = args.argi1;
|
||||
try {
|
||||
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
|
||||
if (stackInfo == null) {
|
||||
// In the case where we've already re-expanded or dismissed the PiP, then
|
||||
// just skip the resize
|
||||
return true;
|
||||
}
|
||||
|
||||
mActivityManager.resizeStack(PINNED_STACK_ID, toBounds,
|
||||
false /* allowResizeInDockedMode */, true /* preserveWindows */,
|
||||
true /* animate */, duration);
|
||||
mBounds.set(toBounds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw, String prefix) {
|
||||
final String innerPrefix = prefix + " ";
|
||||
pw.println(prefix + TAG);
|
||||
|
||||
@@ -154,6 +154,13 @@ public class SystemServicesProxy {
|
||||
Canvas mBgProtectionCanvas;
|
||||
|
||||
private final Handler mHandler = new H();
|
||||
private final Runnable mGcRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
}
|
||||
};
|
||||
|
||||
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
|
||||
|
||||
@@ -365,13 +372,7 @@ public class SystemServicesProxy {
|
||||
* Requests a gc() from the background thread.
|
||||
*/
|
||||
public void gc() {
|
||||
BackgroundThread.getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
}
|
||||
});
|
||||
BackgroundThread.getHandler().post(mGcRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -799,11 +800,8 @@ public class SystemServicesProxy {
|
||||
if (RecentsDebugFlags.Static.EnableMockTasks) return;
|
||||
|
||||
// Remove the task.
|
||||
BackgroundThread.getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAm.removeTask(taskId);
|
||||
}
|
||||
mUiOffloadThread.submit(() -> {
|
||||
mAm.removeTask(taskId);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
|
||||
import com.android.systemui.recents.misc.ForegroundThread;
|
||||
|
||||
/**
|
||||
* The package monitor listens for changes from PackageManager to update the contents of the
|
||||
@@ -36,7 +36,7 @@ public class RecentsPackageMonitor extends PackageMonitor {
|
||||
// We register for events from all users, but will cross-reference them with
|
||||
// packages for the current user and any profiles they have. Ensure that events are
|
||||
// handled in a background thread.
|
||||
register(context, BackgroundThread.get().getLooper(), UserHandle.ALL, true);
|
||||
register(context, ForegroundThread.get().getLooper(), UserHandle.ALL, true);
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.animation.AnimationHandler;
|
||||
import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.IntDef;
|
||||
@@ -30,11 +32,13 @@ import android.os.IBinder;
|
||||
import android.os.Debug;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
import android.view.Choreographer;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.WindowManagerInternal;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -49,7 +53,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
*
|
||||
* The object that is resized needs to implement {@link BoundsAnimationTarget} interface.
|
||||
*
|
||||
* NOTE: All calls to methods in this class should be done on the UI thread
|
||||
* NOTE: All calls to methods in this class should be done on the Animation thread
|
||||
*/
|
||||
public class BoundsAnimationController {
|
||||
private static final boolean DEBUG_LOCAL = false;
|
||||
@@ -111,20 +115,24 @@ public class BoundsAnimationController {
|
||||
private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier();
|
||||
private final Interpolator mFastOutSlowInInterpolator;
|
||||
private boolean mFinishAnimationAfterTransition = false;
|
||||
private final AnimationHandler mAnimationHandler;
|
||||
|
||||
private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
|
||||
|
||||
BoundsAnimationController(Context context, AppTransition transition, Handler handler) {
|
||||
BoundsAnimationController(Context context, AppTransition transition, Handler handler,
|
||||
AnimationHandler animationHandler) {
|
||||
mHandler = handler;
|
||||
mAppTransition = transition;
|
||||
mAppTransition.registerListenerLocked(mAppTransitionNotifier);
|
||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
|
||||
com.android.internal.R.interpolator.fast_out_slow_in);
|
||||
mAnimationHandler = animationHandler;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final class BoundsAnimator extends ValueAnimator
|
||||
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
|
||||
|
||||
private final BoundsAnimationTarget mTarget;
|
||||
private final Rect mFrom = new Rect();
|
||||
private final Rect mTo = new Rect();
|
||||
@@ -350,6 +358,14 @@ public class BoundsAnimationController {
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimationHandler getAnimationHandler() {
|
||||
if (mAnimationHandler != null) {
|
||||
return mAnimationHandler;
|
||||
}
|
||||
return super.getAnimationHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
|
||||
|
||||
@@ -103,6 +103,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.Manifest;
|
||||
import android.Manifest.permission;
|
||||
import android.animation.AnimationHandler;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
@@ -211,6 +212,7 @@ import android.view.inputmethod.InputMethodManagerInternal;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.app.IAssistScreenshotReceiver;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||
import com.android.internal.policy.IShortcutService;
|
||||
@@ -1046,8 +1048,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
mAppTransition = new AppTransition(context, this);
|
||||
mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
|
||||
|
||||
final AnimationHandler animationHandler = new AnimationHandler();
|
||||
animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
|
||||
mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
|
||||
UiThread.getHandler());
|
||||
AnimationThread.getHandler(), animationHandler);
|
||||
|
||||
mActivityManager = ActivityManager.getService();
|
||||
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
|
||||
|
||||
@@ -395,7 +395,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
|
||||
mMockAppTransition = new MockAppTransition(context);
|
||||
mMockAnimator = new MockValueAnimator();
|
||||
mTarget = new TestBoundsAnimationTarget();
|
||||
mController = new BoundsAnimationController(context, mMockAppTransition, handler);
|
||||
mController = new BoundsAnimationController(context, mMockAppTransition, handler, null);
|
||||
mDriver = new BoundsAnimationDriver(mController, mTarget);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user