private static native void nativeMergeTransaction(long transactionObj,
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
+ private static native void nativeSetEarlyWakeup(long transactionObj);
private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
}
/**
+ * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
+ * transaction. This should be used when the caller thinks that the scene is complex enough
+ * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
+ * order not to miss frame deadlines.
+ * <p>
+ * Corresponds to setting ISurfaceComposer::eEarlyWakeup
+ */
+ public Transaction setEarlyWakeup() {
+ nativeSetEarlyWakeup(mNativeObject);
+ return this;
+ }
+
+ /**
* Merge the other transaction into this transaction, clearing the
* other transaction as if it had been applied.
*/
transaction->setAnimationTransaction();
}
+static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setEarlyWakeup();
+}
+
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint zorder) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
(void*)nativeMergeTransaction },
{"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
+ {"nativeSetEarlyWakeup", "(J)V",
+ (void*)nativeSetEarlyWakeup },
{"nativeSetLayer", "(JJI)V",
(void*)nativeSetLayer },
{"nativeSetRelativeLayer", "(JJLandroid/os/IBinder;I)V",
private final Point mPosition = new Point();
private final ThreadLocal<TmpValues> mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new);
private final boolean mCanSkipFirstFrame;
+ private final boolean mIsAppAnimation;
private final Rect mStackBounds = new Rect();
private int mStackClipMode;
private final Rect mTmpRect = new Rect();
public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) {
- this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE);
+ this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE,
+ false /* isAppAnimation */);
}
public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds,
- boolean canSkipFirstFrame, int stackClipMode) {
+ boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation) {
mAnimation = animation;
if (position != null) {
mPosition.set(position.x, position.y);
}
mCanSkipFirstFrame = canSkipFirstFrame;
+ mIsAppAnimation = isAppAnimation;
mStackClipMode = stackClipMode;
if (stackBounds != null) {
mStackBounds.set(stackBounds);
}
@Override
+ public boolean needsEarlyWakeup() {
+ return mIsAppAnimation;
+ }
+
+ @Override
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.println(mAnimation);
}
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
@Test
public void testApply_clipAfter() {
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
// Stack bounds is (0, 0, 10, 10) position is (20, 40)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation,
new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
- STACK_CLIP_AFTER_ANIM);
+ STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
public void testApply_clipBeforeNoAnimationBounds() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
Animation a = createClipRectAnimation(windowCrop, windowCrop);
a.initialize(0, 0, 0, 0);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
}
Rect windowCrop = new Rect(0, 0, 5, 5);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));