Merge "Fix SurfaceViewPositionListener race bugs"

This commit is contained in:
Treehugger Robot
2016-10-10 21:48:52 +00:00
committed by Gerrit Code Review
3 changed files with 25 additions and 33 deletions

View File

@@ -573,8 +573,9 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
bounds.roundOut(); bounds.roundOut();
} }
incStrong(0);
auto functor = std::bind( auto functor = std::bind(
std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this, std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
(jlong) info.canvasContext.getFrameNumber(), (jlong) info.canvasContext.getFrameNumber(),
(jint) bounds.left, (jint) bounds.top, (jint) bounds.left, (jint) bounds.top,
(jint) bounds.right, (jint) bounds.bottom); (jint) bounds.right, (jint) bounds.bottom);
@@ -585,15 +586,18 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override { virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return; if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
if (info) { ATRACE_NAME("SurfaceView position lost");
auto functor = std::bind( JNIEnv* env = jnienv();
std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this, jobject localref = env->NewLocalRef(mWeakRef);
(jlong) info->canvasContext.getFrameNumber()); if (CC_UNLIKELY(!localref)) {
jnienv()->DeleteWeakGlobalRef(mWeakRef);
info->canvasContext.enqueueFrameWork(std::move(functor)); mWeakRef = nullptr;
} else { return;
doNotifyPositionLost(0);
} }
env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
info ? info->canvasContext.getFrameNumber() : 0);
env->DeleteLocalRef(localref);
} }
private: private:
@@ -605,36 +609,23 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
return env; return env;
} }
void doUpdatePosition(jlong frameNumber, jint left, jint top, void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
jint right, jint bottom) { jint right, jint bottom) {
ATRACE_NAME("Update SurfaceView position"); ATRACE_NAME("Update SurfaceView position");
JNIEnv* env = jnienv(); JNIEnv* env = jnienv();
jobject localref = env->NewLocalRef(mWeakRef); jobject localref = env->NewLocalRef(mWeakRef);
if (CC_UNLIKELY(!localref)) { if (CC_UNLIKELY(!localref)) {
jnienv()->DeleteWeakGlobalRef(mWeakRef); env->DeleteWeakGlobalRef(mWeakRef);
mWeakRef = nullptr; mWeakRef = nullptr;
return; } else {
env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
frameNumber, left, top, right, bottom);
env->DeleteLocalRef(localref);
} }
env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod, // We need to release ourselves here
frameNumber, left, top, right, bottom); decStrong(0);
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;

View File

@@ -232,7 +232,7 @@ public:
// the frameNumber to appropriately batch/synchronize these transactions. // the frameNumber to appropriately batch/synchronize these transactions.
// There is no other filtering/batching to ensure that only the "final" // There is no other filtering/batching to ensure that only the "final"
// state called once per frame. // state called once per frame.
class ANDROID_API PositionListener { class ANDROID_API PositionListener : public VirtualLightRefBase {
public: public:
virtual ~PositionListener() {} virtual ~PositionListener() {}
// Called when the RenderNode's position changes // Called when the RenderNode's position changes
@@ -247,7 +247,7 @@ public:
// before the RenderNode is used for drawing. // before the RenderNode is used for drawing.
// RenderNode takes ownership of the pointer // RenderNode takes ownership of the pointer
ANDROID_API void setPositionListener(PositionListener* listener) { ANDROID_API void setPositionListener(PositionListener* listener) {
mPositionListener.reset(listener); mPositionListener = listener;
} }
// This is only modified in MODE_FULL, so it can be safely accessed // This is only modified in MODE_FULL, so it can be safely accessed
@@ -366,7 +366,7 @@ private:
// mDisplayList, not mStagingDisplayList. // mDisplayList, not mStagingDisplayList.
uint32_t mParentCount; uint32_t mParentCount;
std::unique_ptr<PositionListener> mPositionListener; sp<PositionListener> mPositionListener;
}; // class RenderNode }; // class RenderNode
} /* namespace uirenderer */ } /* namespace uirenderer */

View File

@@ -783,6 +783,7 @@ void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
} }
sp<FuncTask> task(new FuncTask()); sp<FuncTask> task(new FuncTask());
task->func = func; task->func = func;
mFrameFences.push_back(task);
mFrameWorkProcessor->add(task); mFrameWorkProcessor->add(task);
} }