Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9408d4a authored by Robert Carr's avatar Robert Carr
Browse files

PiP animation: Move window with resize when ending animation.

At the end of the animation (when going from larger to smaller),
we are left with a scaled surface, that we want to seamlessly
resize to an unscaled surface of the new size. Because we have scaled
the shadow region of the surface, the position of the content
will differ before and after the resize applies. We use new
SurfaceFlinger API to cause position updates to apply after
resize. Because we have to switch into SCALING_MODE_FREEZE,
we could end up prematurely cropping the window, so we
switch to using screen space crop for the pinned stack.

Bug: 28899837
Change-Id: I9b762a237413e4fa3d432e67d30c7125bfef484c
parent 3207d8f8
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ public class SurfaceControl {

    private static native void nativeSetLayer(long nativeObject, int zorder);
    private static native void nativeSetPosition(long nativeObject, float x, float y);
    private static native void nativeSetPositionAppliesWithResize(long nativeObject);
    private static native void nativeSetSize(long nativeObject, int w, int h);
    private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
    private static native void nativeSetAlpha(long nativeObject, float alpha);
@@ -407,6 +408,16 @@ public class SurfaceControl {
        nativeSetPosition(mNativeObject, x, y);
    }

    /**
     * If the size changes in this transaction, position updates specified
     * in this transaction will not complete until a buffer of the new size
     * arrives.
     */
    public void setPositionAppliesWithResize() {
        checkNotReleased();
        nativeSetPositionAppliesWithResize(mNativeObject);
    }

    public void setSize(int w, int h) {
        checkNotReleased();
        nativeSetSize(mNativeObject, w, h);
+11 −0
Original line number Diff line number Diff line
@@ -248,6 +248,15 @@ static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfl
    }
}

static void nativeSetPositionAppliesWithResize(JNIEnv* env, jclass clazz,
        jlong nativeObject) {
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    status_t err = ctrl->setPositionAppliesWithResize();
    if (err < 0 && err != NO_INIT) {
        doThrowIAE(env);
    }
}

static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    status_t err = ctrl->setSize(w, h);
@@ -658,6 +667,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeSetLayer },
    {"nativeSetPosition", "(JFF)V",
            (void*)nativeSetPosition },
    {"nativeSetPositionAppliesWithResize", "(J)V",
            (void*)nativeSetPositionAppliesWithResize },
    {"nativeSetSize", "(JII)V",
            (void*)nativeSetSize },
    {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
+29 −6
Original line number Diff line number Diff line
@@ -1314,7 +1314,6 @@ class WindowStateAnimator {
    }

    private int resolveStackClip() {

        // App animation overrides window animation stack clip mode.
        if (mAppAnimator != null && mAppAnimator.animation != null) {
            return mAppAnimator.getStackClip();
@@ -1420,6 +1419,9 @@ class WindowStateAnimator {
        // aren't observing known issues here outside of PiP resizing. (Typically
        // the other windows that use -1 are PopupWindows which aren't likely
        // to be rendering while we resize).

        boolean wasForceScaled = mForceScaleUntilResize;

        if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
            mSurfaceResized = mSurfaceController.setSizeInTransaction(
                    mTmpSize.width(), mTmpSize.height(), recoveringMemory);
@@ -1428,13 +1430,17 @@ class WindowStateAnimator {
        }
        mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;


        calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);

        float surfaceWidth = mSurfaceController.getWidth();
        float surfaceHeight = mSurfaceController.getHeight();

        if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
            int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
            int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
            float surfaceWidth = mSurfaceController.getWidth();
            float surfaceHeight = mSurfaceController.getHeight();
            if (!mForceScaleUntilResize) {
                mSurfaceController.forceScaleableInTransaction(true);
            }
            // We want to calculate the scaling based on the content area, not based on
            // the entire surface, so that we scale in sync with windows that don't have insets.
            mExtraHScale = (mTmpClipRect.width() - hInsets) / (float)(surfaceWidth - hInsets);
@@ -1455,7 +1461,8 @@ class WindowStateAnimator {
            posX += w.getAttrs().surfaceInsets.left * (1 - mExtraHScale);
            posY += w.getAttrs().surfaceInsets.top * (1 - mExtraVScale);

            mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory);
            mSurfaceController.setPositionInTransaction((float)Math.floor(posX),
                    (float)Math.floor(posY), recoveringMemory);

            // Since we are scaled to fit in our previously desired crop, we can now
            // expose the whole window in buffer space, and not risk extending
@@ -1475,6 +1482,22 @@ class WindowStateAnimator {
                    recoveringMemory);
        }

        // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
        // to prevent further updates until buffer latch. Normally position
        // would continue to apply immediately. But we need a different position
        // before and after resize (since we have scaled the shadows, as discussed
        // above).
        if (wasForceScaled && !mForceScaleUntilResize) {
            mSurfaceController.setPositionAppliesWithResizeInTransaction(true);
            mSurfaceController.forceScaleableInTransaction(false);
        }
        if (w.inPinnedWorkspace()) {
            mTmpClipRect.set(0, 0, -1, -1);
            task.mStack.getDimBounds(mTmpFinalClipRect);
            mTmpFinalClipRect.inset(-w.mAttrs.surfaceInsets.left, -w.mAttrs.surfaceInsets.top,
                    -w.mAttrs.surfaceInsets.right, -w.mAttrs.surfaceInsets.bottom);
        }

        updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory);

        mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
+12 −1
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ class WindowSurfaceController {
        if (SHOW_TRANSACTIONS) logSurface(
                "CROP " + clipRect.toShortString(), null);
        try {
            if (clipRect.width() > 0 && clipRect.height() > 0) {
            if (clipRect.width() != 0 && clipRect.height() != 0) {
                mSurfaceControl.setWindowCrop(clipRect);
                mHiddenForCrop = false;
                updateVisibility();
@@ -236,6 +236,10 @@ class WindowSurfaceController {
        }
    }

    void setPositionAppliesWithResizeInTransaction(boolean recoveringMemory) {
        mSurfaceControl.setPositionAppliesWithResize();
    }

    void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
            boolean recoveringMemory) {
        try {
@@ -553,6 +557,13 @@ class WindowSurfaceController {
            super.setPosition(x, y);
        }

        @Override
        public void setPositionAppliesWithResize() {
            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPositionAppliesWithResize(): OLD: "
                    + this + ". Called by" + Debug.getCallers(9));
            super.setPositionAppliesWithResize();
        }

        @Override
        public void setSize(int w, int h) {
            if (w != mSize.x || h != mSize.y) {