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

Commit f5159155 authored by John Reck's avatar John Reck Committed by android-build-merger
Browse files

Merge \"DO NOT MERGE Move SurfaceView offscreen if the app stops drawing it\" into nyc-dev

am: d11b5e66

Change-Id: I1caf2fbac785c68c6afeb61b60493e728a83a670
parents cb0649f7 d11b5e66
Loading
Loading
Loading
Loading
+44 −17
Original line number Diff line number Diff line
@@ -464,7 +464,8 @@ public class SurfaceView extends View {
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
            getLocationInWindow(mLocation);

            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                    + "Changes: creating=" + creating
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged
                    + " left=" + (mWindowSpaceLeft != mLocation[0])
@@ -534,7 +535,8 @@ public class SurfaceView extends View {
                    mReportDrawNeeded = false;
                    mDrawingStopped = !visible;

                    if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
                    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                            + "Cur surface: " + mSurface);

                    relayoutResult = mSession.relayout(
                        mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
@@ -547,7 +549,8 @@ public class SurfaceView extends View {
                        reportDrawNeeded = true;
                    }

                    if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
                    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                            + "New surface: " + mNewSurface
                            + ", vis=" + visible + ", frame=" + mWinFrame);

                    mSurfaceFrame.left = 0;
@@ -581,7 +584,8 @@ public class SurfaceView extends View {
                    if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                        mSurfaceCreated = false;
                        if (mSurface.isValid()) {
                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                    + "visibleChanged -- surfaceDestroyed");
                            callbacks = getSurfaceCallbacks();
                            for (SurfaceHolder.Callback c : callbacks) {
                                c.surfaceDestroyed(mSurfaceHolder);
@@ -594,7 +598,8 @@ public class SurfaceView extends View {
                        if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
                            mSurfaceCreated = true;
                            mIsCreating = true;
                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                    + "visibleChanged -- surfaceCreated");
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
                            }
@@ -604,7 +609,8 @@ public class SurfaceView extends View {
                        }
                        if (creating || formatChanged || sizeChanged
                                || visibleChanged || realSizeChanged) {
                            if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                    + "surfaceChanged -- format=" + mFormat
                                    + " w=" + myWidth + " h=" + myHeight);
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
@@ -614,7 +620,8 @@ public class SurfaceView extends View {
                            }
                        }
                        if (redrawNeeded) {
                            if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                    + "surfaceRedrawNeeded");
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
                            }
@@ -629,7 +636,8 @@ public class SurfaceView extends View {
                } finally {
                    mIsCreating = false;
                    if (redrawNeeded) {
                        if (DEBUG) Log.i(TAG, "finishedDrawing");
                        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                + "finishedDrawing");
                        mSession.finishDrawing(mWindow);
                    }
                    mSession.performDeferredDestroy(mWindow);
@@ -663,8 +671,9 @@ public class SurfaceView extends View {
                }

                try {
                    Log.d(TAG, String.format("updateWindowPosition UI, " +
                            "postion = [%d, %d, %d, %d]", mWinFrame.left, mWinFrame.top,
                    Log.d(TAG, String.format("%d updateWindowPosition UI, " +
                            "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
                            mWinFrame.left, mWinFrame.top,
                            mWinFrame.right, mWinFrame.bottom));
                    mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
                            mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
@@ -697,9 +706,9 @@ public class SurfaceView extends View {
        }
        try {
            if (DEBUG) {
                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
                        right, bottom));
                Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " +
                        "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
                        frameNumber, left, top, right, bottom));
            }
            // Just using mRTLastReportedPosition as a dummy rect here
            session.repositionChild(window, left, top, right, bottom,
@@ -712,6 +721,25 @@ public class SurfaceView extends View {
        }
    }

    /**
     * Called by native on RenderThread to notify that the window is no longer in the
     * draw tree
     * @hide
     */
    public final void windowPositionLostRT(long frameNumber) {
        if (DEBUG) {
            Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d",
                    System.identityHashCode(this), frameNumber));
        }
        // TODO: This is a bit of a hack as we don't have an API to report to WM
        // to hide a window with a frameNumber, so just shift the window very far into
        // negative space which will do effectively the same thing.
        // Use the last reported size to avoid influencing the size of the bufferqueue
        int x = -1000 - mRTLastReportedPosition.width();
        int y = -1000 - mRTLastReportedPosition.height();
        updateWindowPositionRT(frameNumber, x, y, -1000, -1000);
    }

    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
        SurfaceHolder.Callback callbacks[];
        synchronized (mCallbacks) {
@@ -750,8 +778,7 @@ public class SurfaceView extends View {
                boolean alwaysConsumeNavBar) {
            SurfaceView surfaceView = mSurfaceView.get();
            if (surfaceView != null) {
                if (DEBUG) Log.v(
                        "SurfaceView", surfaceView + " got resized: w=" + frame.width()
                if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
                        + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                surfaceView.mSurfaceLock.lock();
                try {
@@ -907,7 +934,7 @@ public class SurfaceView extends View {
        private final Canvas internalLockCanvas(Rect dirty) {
            mSurfaceLock.lock();

            if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
                    + mDrawingStopped + ", win=" + mWindow);

            Canvas c = null;
@@ -919,7 +946,7 @@ public class SurfaceView extends View {
                }
            }

            if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c);
            if (c != null) {
                mLastLockTime = SystemClock.uptimeMillis();
                return c;
+32 −0
Original line number Diff line number Diff line
@@ -534,6 +534,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
// ----------------------------------------------------------------------------

jmethodID gSurfaceViewPositionUpdateMethod;
jmethodID gSurfaceViewPositionLostMethod;

static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
        jlong renderNodePtr, jobject surfaceview) {
@@ -581,6 +582,20 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
            info.canvasContext.enqueueFrameWork(std::move(functor));
        }

        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
            if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;

            if (info) {
                auto functor = std::bind(
                    std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this,
                    (jlong) info->canvasContext.getFrameNumber());

                info->canvasContext.enqueueFrameWork(std::move(functor));
            } else {
                doNotifyPositionLost(0);
            }
        }

    private:
        JNIEnv* jnienv() {
            JNIEnv* env;
@@ -607,6 +622,21 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
            env->DeleteLocalRef(localref);
        }

        void doNotifyPositionLost(jlong frameNumber) {
            ATRACE_NAME("SurfaceView position lost");

            JNIEnv* env = jnienv();
            jobject localref = env->NewLocalRef(mWeakRef);
            if (CC_UNLIKELY(!localref)) {
                jnienv()->DeleteWeakGlobalRef(mWeakRef);
                mWeakRef = nullptr;
                return;
            }

            env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber);
            env->DeleteLocalRef(localref);
        }

        JavaVM* mVm;
        jobject mWeakRef;
    };
@@ -701,6 +731,8 @@ int register_android_view_RenderNode(JNIEnv* env) {
    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
            "updateWindowPositionRT", "(JIIII)V");
    gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
            "windowPositionLostRT", "(J)V");
    clazz = FindClassOrDie(env, "android/view/RenderNode");
    gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz,
            "onRenderNodeDetached", "()V");
+13 −10
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) {
}
#endif

void RenderNode::syncDisplayList(TreeObserver* observer) {
void RenderNode::syncDisplayList(TreeInfo* info) {
    // Make sure we inc first so that we don't fluctuate between 0 and 1,
    // which would thrash the layer cache
    if (mStagingDisplayList) {
@@ -472,7 +472,7 @@ void RenderNode::syncDisplayList(TreeObserver* observer) {
            child->renderNode->incParentRefCount();
        }
    }
    deleteDisplayList(observer);
    deleteDisplayList(info ? info->observer : nullptr, info);
    mDisplayList = mStagingDisplayList;
    mStagingDisplayList = nullptr;
    if (mDisplayList) {
@@ -491,15 +491,15 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
        // Damage with the old display list first then the new one to catch any
        // changes in isRenderable or, in the future, bounds
        damageSelf(info);
        syncDisplayList(info.observer);
        syncDisplayList(&info);
        damageSelf(info);
    }
}

void RenderNode::deleteDisplayList(TreeObserver* observer) {
void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
    if (mDisplayList) {
        for (auto&& child : mDisplayList->getChildren()) {
            child->renderNode->decParentRefCount(observer);
            child->renderNode->decParentRefCount(observer, info);
        }
    }
    delete mDisplayList;
@@ -531,35 +531,38 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL
    }
}

void RenderNode::destroyHardwareResources(TreeObserver* observer) {
void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
    if (mLayer) {
        destroyLayer(mLayer);
        mLayer = nullptr;
    }
    if (mDisplayList) {
        for (auto&& child : mDisplayList->getChildren()) {
            child->renderNode->destroyHardwareResources(observer);
            child->renderNode->destroyHardwareResources(observer, info);
        }
        if (mNeedsDisplayListSync) {
            // Next prepare tree we are going to push a new display list, so we can
            // drop our current one now
            deleteDisplayList(observer);
            deleteDisplayList(observer, info);
        }
    }
}

void RenderNode::decParentRefCount(TreeObserver* observer) {
void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) {
    LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
    mParentCount--;
    if (!mParentCount) {
        if (observer) {
            observer->onMaybeRemovedFromTree(this);
        }
        if (CC_UNLIKELY(mPositionListener.get())) {
            mPositionListener->onPositionLost(*this, info);
        }
        // If a child of ours is being attached to our parent then this will incorrectly
        // destroy its hardware resources. However, this situation is highly unlikely
        // and the failure is "just" that the layer is re-created, so this should
        // be safe enough
        destroyHardwareResources(observer);
        destroyHardwareResources(observer, info);
    }
}

+13 −4
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ public:
    }

    ANDROID_API virtual void prepareTree(TreeInfo& info);
    void destroyHardwareResources(TreeObserver* observer);
    void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr);

    // UI thread only!
    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
@@ -228,10 +228,19 @@ public:
    OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
#endif

    // Note: The position callbacks are relying on the listener using
    // the frameNumber to appropriately batch/synchronize these transactions.
    // There is no other filtering/batching to ensure that only the "final"
    // state called once per frame.
    class ANDROID_API PositionListener {
    public:
        virtual ~PositionListener() {}
        // Called when the RenderNode's position changes
        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
        // Called when the RenderNode no longer has a position. As in, it's
        // no longer being drawn.
        // Note, tree info might be null
        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
    };

    // Note this is not thread safe, this needs to be called
@@ -306,7 +315,7 @@ private:


    void syncProperties();
    void syncDisplayList(TreeObserver* observer);
    void syncDisplayList(TreeInfo* info);

    void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
    void pushStagingPropertiesChanges(TreeInfo& info);
@@ -317,11 +326,11 @@ private:
#endif
    void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
    void pushLayerUpdate(TreeInfo& info);
    void deleteDisplayList(TreeObserver* observer);
    void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
    void damageSelf(TreeInfo& info);

    void incParentRefCount() { mParentCount++; }
    void decParentRefCount(TreeObserver* observer);
    void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);

    String8 mName;
    sp<VirtualLightRefBase> mUserContext;