Ensure that we use SF Vsync Choreographer for the PiP transition.
- Move the bounds animation onto the animation thread
- Remove existing code referencing the old sf-vsync choreographer
- Add ability for ValueAnimator subclasses to reference a different
AnimationHandler, which uses a different FrameCallbackProvider with the
sf-vsync choreographer in the animations that require it
- Ensure that PiP touch events are batched and sent aligned with the
sf-vsync
- Move GC onto its own thread to not block other BackgroundThread calls
Bug: 36371375
Test: android.server.cts.ActivityManagerPinnedStackTests
Test: bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
Test: go/wm-smoke
Change-Id: I6a41b35a4e4d4d6dbea82c2673452825fe3ffa58
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e686a89..ee89ca8 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1469,24 +1469,21 @@
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 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();
+ }
}
diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
new file mode 100644
index 0000000..931eb99
--- /dev/null
+++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
index 867c15c..6733421 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
@@ -21,12 +21,15 @@
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 @@
}
/**
- * 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
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 013b9ac..0f69f47 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -573,13 +573,11 @@
}
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);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 9fa7ff6..b8771d7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -22,6 +22,7 @@
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.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 @@
/**
* 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
+ " 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 @@
+ " 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 @@
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);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 1f13830..c66b2dd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -154,6 +154,13 @@
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 @@
* 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 @@
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);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index 1f82c16..308cece 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -20,9 +20,9 @@
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 @@
// 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();
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 410efcd..7d13889 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -20,6 +20,8 @@
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.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 @@
*
* 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 @@
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 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,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 768b03a..77e2f71 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -103,6 +103,7 @@
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 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 @@
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);
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index ee09f4b..9d32496 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -395,7 +395,7 @@
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);
}