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

Commit e66dedf3 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge "Move SurfaceView offscreen if the app stops drawing it" into nyc-mr1-dev

parents ffaec892 aa6e84f2
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
@@ -474,7 +474,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) {
@@ -482,7 +482,7 @@ void RenderNode::syncDisplayList(TreeObserver* observer) {
            child->renderNode->incParentRefCount();
        }
    }
    deleteDisplayList(observer);
    deleteDisplayList(info ? info->observer : nullptr, info);
    mDisplayList = mStagingDisplayList;
    mStagingDisplayList = nullptr;
    if (mDisplayList) {
@@ -501,15 +501,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;
@@ -541,35 +541,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;