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

Commit d11b5e66 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents fc275d24 34bf49e4
Loading
Loading
Loading
Loading
+44 −17
Original line number Original line Diff line number Diff line
@@ -464,7 +464,8 @@ public class SurfaceView extends View {
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
            getLocationInWindow(mLocation);
            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
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged
                    + " visible=" + visibleChanged
                    + " left=" + (mWindowSpaceLeft != mLocation[0])
                    + " left=" + (mWindowSpaceLeft != mLocation[0])
@@ -534,7 +535,8 @@ public class SurfaceView extends View {
                    mReportDrawNeeded = false;
                    mReportDrawNeeded = false;
                    mDrawingStopped = !visible;
                    mDrawingStopped = !visible;


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


                    relayoutResult = mSession.relayout(
                    relayoutResult = mSession.relayout(
                        mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
                        mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
@@ -547,7 +549,8 @@ public class SurfaceView extends View {
                        reportDrawNeeded = true;
                        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);
                            + ", vis=" + visible + ", frame=" + mWinFrame);


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


                try {
                try {
                    Log.d(TAG, String.format("updateWindowPosition UI, " +
                    Log.d(TAG, String.format("%d updateWindowPosition UI, " +
                            "postion = [%d, %d, %d, %d]", mWinFrame.left, mWinFrame.top,
                            "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
                            mWinFrame.left, mWinFrame.top,
                            mWinFrame.right, mWinFrame.bottom));
                            mWinFrame.right, mWinFrame.bottom));
                    mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
                    mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
                            mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
                            mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
@@ -697,9 +706,9 @@ public class SurfaceView extends View {
        }
        }
        try {
        try {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
                Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " +
                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
                        "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
                        right, bottom));
                        frameNumber, left, top, right, bottom));
            }
            }
            // Just using mRTLastReportedPosition as a dummy rect here
            // Just using mRTLastReportedPosition as a dummy rect here
            session.repositionChild(window, left, top, right, bottom,
            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() {
    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
        SurfaceHolder.Callback callbacks[];
        SurfaceHolder.Callback callbacks[];
        synchronized (mCallbacks) {
        synchronized (mCallbacks) {
@@ -750,8 +778,7 @@ public class SurfaceView extends View {
                boolean alwaysConsumeNavBar) {
                boolean alwaysConsumeNavBar) {
            SurfaceView surfaceView = mSurfaceView.get();
            SurfaceView surfaceView = mSurfaceView.get();
            if (surfaceView != null) {
            if (surfaceView != null) {
                if (DEBUG) Log.v(
                if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
                        "SurfaceView", surfaceView + " got resized: w=" + frame.width()
                        + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                        + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                surfaceView.mSurfaceLock.lock();
                surfaceView.mSurfaceLock.lock();
                try {
                try {
@@ -907,7 +934,7 @@ public class SurfaceView extends View {
        private final Canvas internalLockCanvas(Rect dirty) {
        private final Canvas internalLockCanvas(Rect dirty) {
            mSurfaceLock.lock();
            mSurfaceLock.lock();


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


            Canvas c = null;
            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) {
            if (c != null) {
                mLastLockTime = SystemClock.uptimeMillis();
                mLastLockTime = SystemClock.uptimeMillis();
                return c;
                return c;
+32 −0
Original line number Original line Diff line number Diff line
@@ -534,6 +534,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


jmethodID gSurfaceViewPositionUpdateMethod;
jmethodID gSurfaceViewPositionUpdateMethod;
jmethodID gSurfaceViewPositionLostMethod;


static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
        jlong renderNodePtr, jobject surfaceview) {
        jlong renderNodePtr, jobject surfaceview) {
@@ -581,6 +582,20 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
            info.canvasContext.enqueueFrameWork(std::move(functor));
            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:
    private:
        JNIEnv* jnienv() {
        JNIEnv* jnienv() {
            JNIEnv* env;
            JNIEnv* env;
@@ -607,6 +622,21 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
            env->DeleteLocalRef(localref);
            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;
        JavaVM* mVm;
        jobject mWeakRef;
        jobject mWeakRef;
    };
    };
@@ -701,6 +731,8 @@ int register_android_view_RenderNode(JNIEnv* env) {
    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
            "updateWindowPositionRT", "(JIIII)V");
            "updateWindowPositionRT", "(JIIII)V");
    gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
            "windowPositionLostRT", "(J)V");
    clazz = FindClassOrDie(env, "android/view/RenderNode");
    clazz = FindClassOrDie(env, "android/view/RenderNode");
    gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz,
    gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz,
            "onRenderNodeDetached", "()V");
            "onRenderNodeDetached", "()V");
+13 −10
Original line number Original line Diff line number Diff line
@@ -464,7 +464,7 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) {
}
}
#endif
#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,
    // Make sure we inc first so that we don't fluctuate between 0 and 1,
    // which would thrash the layer cache
    // which would thrash the layer cache
    if (mStagingDisplayList) {
    if (mStagingDisplayList) {
@@ -472,7 +472,7 @@ void RenderNode::syncDisplayList(TreeObserver* observer) {
            child->renderNode->incParentRefCount();
            child->renderNode->incParentRefCount();
        }
        }
    }
    }
    deleteDisplayList(observer);
    deleteDisplayList(info ? info->observer : nullptr, info);
    mDisplayList = mStagingDisplayList;
    mDisplayList = mStagingDisplayList;
    mStagingDisplayList = nullptr;
    mStagingDisplayList = nullptr;
    if (mDisplayList) {
    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
        // Damage with the old display list first then the new one to catch any
        // changes in isRenderable or, in the future, bounds
        // changes in isRenderable or, in the future, bounds
        damageSelf(info);
        damageSelf(info);
        syncDisplayList(info.observer);
        syncDisplayList(&info);
        damageSelf(info);
        damageSelf(info);
    }
    }
}
}


void RenderNode::deleteDisplayList(TreeObserver* observer) {
void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
    if (mDisplayList) {
    if (mDisplayList) {
        for (auto&& child : mDisplayList->getChildren()) {
        for (auto&& child : mDisplayList->getChildren()) {
            child->renderNode->decParentRefCount(observer);
            child->renderNode->decParentRefCount(observer, info);
        }
        }
    }
    }
    delete mDisplayList;
    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) {
    if (mLayer) {
        destroyLayer(mLayer);
        destroyLayer(mLayer);
        mLayer = nullptr;
        mLayer = nullptr;
    }
    }
    if (mDisplayList) {
    if (mDisplayList) {
        for (auto&& child : mDisplayList->getChildren()) {
        for (auto&& child : mDisplayList->getChildren()) {
            child->renderNode->destroyHardwareResources(observer);
            child->renderNode->destroyHardwareResources(observer, info);
        }
        }
        if (mNeedsDisplayListSync) {
        if (mNeedsDisplayListSync) {
            // Next prepare tree we are going to push a new display list, so we can
            // Next prepare tree we are going to push a new display list, so we can
            // drop our current one now
            // 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!");
    LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
    mParentCount--;
    mParentCount--;
    if (!mParentCount) {
    if (!mParentCount) {
        if (observer) {
        if (observer) {
            observer->onMaybeRemovedFromTree(this);
            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
        // 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
        // destroy its hardware resources. However, this situation is highly unlikely
        // and the failure is "just" that the layer is re-created, so this should
        // and the failure is "just" that the layer is re-created, so this should
        // be safe enough
        // be safe enough
        destroyHardwareResources(observer);
        destroyHardwareResources(observer, info);
    }
    }
}
}


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


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


    // UI thread only!
    // UI thread only!
    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
@@ -228,10 +228,19 @@ public:
    OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
    OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
#endif
#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 {
    class ANDROID_API PositionListener {
    public:
    public:
        virtual ~PositionListener() {}
        virtual ~PositionListener() {}
        // Called when the RenderNode's position changes
        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
        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
    // Note this is not thread safe, this needs to be called
@@ -306,7 +315,7 @@ private:




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


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


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


    String8 mName;
    String8 mName;
    sp<VirtualLightRefBase> mUserContext;
    sp<VirtualLightRefBase> mUserContext;