Loading core/java/android/view/RenderNode.java +8 −11 Original line number Diff line number Diff line Loading @@ -139,9 +139,6 @@ public class RenderNode { RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024); } // Note: written by native when display lists are detached private boolean mValid; // Do not access directly unless you are ThreadedRenderer final long mNativeRenderNode; private final View mOwningView; Loading Loading @@ -233,7 +230,6 @@ public class RenderNode { long displayList = canvas.finishRecording(); nSetDisplayList(mNativeRenderNode, displayList); canvas.recycle(); mValid = true; } /** Loading @@ -242,10 +238,7 @@ public class RenderNode { * obsolete resources after related resources are gone. */ public void discardDisplayList() { if (!mValid) return; nSetDisplayList(mNativeRenderNode, 0); mValid = false; } /** Loading @@ -254,10 +247,12 @@ public class RenderNode { * * @return boolean true if the display list is able to be replayed, false otherwise. */ public boolean isValid() { return mValid; } public boolean isValid() { return nIsValid(mNativeRenderNode); } long getNativeDisplayList() { if (!mValid) { if (!isValid()) { throw new IllegalStateException("The display list is not valid."); } return mNativeRenderNode; Loading Loading @@ -827,8 +822,7 @@ public class RenderNode { // Regular JNI methods /////////////////////////////////////////////////////////////////////////// // Intentionally not static because it acquires a reference to 'this' private native long nCreate(String name); private static native long nCreate(String name); private static native long nGetNativeFinalizer(); private static native void nOutput(long renderNode); Loading @@ -853,6 +847,9 @@ public class RenderNode { // @CriticalNative methods /////////////////////////////////////////////////////////////////////////// @CriticalNative private static native boolean nIsValid(long renderNode); // Matrix @CriticalNative Loading core/java/android/view/ThreadedRenderer.java +0 −9 Original line number Diff line number Diff line Loading @@ -496,15 +496,6 @@ public final class ThreadedRenderer { private static void destroyResources(View view) { view.destroyHardwareResources(); if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; int count = group.getChildCount(); for (int i = 0; i < count; i++) { destroyResources(group.getChildAt(i)); } } } /** Loading core/java/android/view/View.java +8 −10 Original line number Diff line number Diff line Loading @@ -16613,11 +16613,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @CallSuper protected void destroyHardwareResources() { // Although the Layer will be destroyed by RenderNode, we want to release // the staging display list, which is also a signal to RenderNode that it's // safe to free its copy of the display list as it knows that we will // push an updated DisplayList if we try to draw again resetDisplayList(); if (mOverlay != null) { mOverlay.getOverlayView().destroyHardwareResources(); } if (mGhostView != null) { mGhostView.destroyHardwareResources(); } } /** Loading Loading @@ -16788,11 +16789,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void resetDisplayList() { if (mRenderNode.isValid()) { mRenderNode.discardDisplayList(); } if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { if (mBackgroundRenderNode != null) { mBackgroundRenderNode.discardDisplayList(); } } core/java/android/view/ViewGroup.java +10 −0 Original line number Diff line number Diff line Loading @@ -4597,6 +4597,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager clearCachedLayoutMode(); } /** @hide */ @Override protected void destroyHardwareResources() { super.destroyHardwareResources(); int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).destroyHardwareResources(); } } /** * Adds a view during layout. This is useful if in your onLayout() method, * you need to add more views (as does the list view for example). Loading core/jni/android_view_RenderNode.cpp +7 −70 Original line number Diff line number Diff line Loading @@ -43,57 +43,6 @@ using namespace uirenderer; ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \ : false) static JNIEnv* getenv(JavaVM* vm) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); } return env; } static jfieldID gRenderNode_validFieldID; class RenderNodeContext : public VirtualLightRefBase { public: RenderNodeContext(JNIEnv* env, jobject jobjRef) { env->GetJavaVM(&mVm); // This holds a weak ref because otherwise there's a cyclic global ref // with this holding a strong global ref to the view which holds // a strong ref to RenderNode which holds a strong ref to this. mWeakRef = env->NewWeakGlobalRef(jobjRef); } virtual ~RenderNodeContext() { JNIEnv* env = getenv(mVm); env->DeleteWeakGlobalRef(mWeakRef); } jobject acquireLocalRef(JNIEnv* env) { return env->NewLocalRef(mWeakRef); } private: JavaVM* mVm; jweak mWeakRef; }; // Called by ThreadedRenderer's JNI layer void onRenderNodeRemoved(JNIEnv* env, RenderNode* node) { auto context = reinterpret_cast<RenderNodeContext*>(node->getUserContext()); if (!context) return; jobject jnode = context->acquireLocalRef(env); if (!jnode) { // The owning node has been GC'd, release the context node->setUserContext(nullptr); return; } // Update the valid field, since native has already removed // the staging DisplayList env->SetBooleanField(jnode, gRenderNode_validFieldID, false); env->DeleteLocalRef(jnode); } // ---------------------------------------------------------------------------- // DisplayList view properties // ---------------------------------------------------------------------------- Loading @@ -108,8 +57,7 @@ static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlo return renderNode->getDebugSize(); } static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz, jstring name) { static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) { RenderNode* renderNode = new RenderNode(); renderNode->incStrong(0); if (name != NULL) { Loading @@ -117,7 +65,6 @@ static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz, renderNode->setName(textArray); env->ReleaseStringUTFChars(name, textArray); } renderNode->setUserContext(new RenderNodeContext(env, thiz)); return reinterpret_cast<jlong>(renderNode); } Loading @@ -132,22 +79,13 @@ static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env, static void android_view_RenderNode_setDisplayList(JNIEnv* env, jobject clazz, jlong renderNodePtr, jlong displayListPtr) { class RemovedObserver : public TreeObserver { public: virtual void onMaybeRemovedFromTree(RenderNode* node) override { maybeRemovedNodes.insert(sp<RenderNode>(node)); } std::set< sp<RenderNode> > maybeRemovedNodes; }; RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr); RemovedObserver observer; renderNode->setStagingDisplayList(newData, &observer); for (auto& node : observer.maybeRemovedNodes) { if (node->hasParents()) continue; onRenderNodeRemoved(env, node.get()); renderNode->setStagingDisplayList(newData); } static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) { return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid(); } // ---------------------------------------------------------------------------- Loading Loading @@ -621,6 +559,7 @@ static const JNINativeMethod gMethods[] = { // ---------------------------------------------------------------------------- // Critical JNI via @CriticalNative annotation in RenderNode.java // ---------------------------------------------------------------------------- { "nIsValid", "(J)Z", (void*) android_view_RenderNode_isValid }, { "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType }, { "nSetLayerPaint", "(JJ)Z", (void*) android_view_RenderNode_setLayerPaint }, { "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix }, Loading Loading @@ -691,8 +630,6 @@ int register_android_view_RenderNode(JNIEnv* env) { "updateWindowPosition_renderWorker", "(JIIII)V"); gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz, "windowPositionLost_uiRtSync", "(J)V"); clazz = FindClassOrDie(env, "android/view/RenderNode"); gRenderNode_validFieldID = GetFieldIDOrDie(env, clazz, "mValid", "Z"); return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } Loading Loading
core/java/android/view/RenderNode.java +8 −11 Original line number Diff line number Diff line Loading @@ -139,9 +139,6 @@ public class RenderNode { RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024); } // Note: written by native when display lists are detached private boolean mValid; // Do not access directly unless you are ThreadedRenderer final long mNativeRenderNode; private final View mOwningView; Loading Loading @@ -233,7 +230,6 @@ public class RenderNode { long displayList = canvas.finishRecording(); nSetDisplayList(mNativeRenderNode, displayList); canvas.recycle(); mValid = true; } /** Loading @@ -242,10 +238,7 @@ public class RenderNode { * obsolete resources after related resources are gone. */ public void discardDisplayList() { if (!mValid) return; nSetDisplayList(mNativeRenderNode, 0); mValid = false; } /** Loading @@ -254,10 +247,12 @@ public class RenderNode { * * @return boolean true if the display list is able to be replayed, false otherwise. */ public boolean isValid() { return mValid; } public boolean isValid() { return nIsValid(mNativeRenderNode); } long getNativeDisplayList() { if (!mValid) { if (!isValid()) { throw new IllegalStateException("The display list is not valid."); } return mNativeRenderNode; Loading Loading @@ -827,8 +822,7 @@ public class RenderNode { // Regular JNI methods /////////////////////////////////////////////////////////////////////////// // Intentionally not static because it acquires a reference to 'this' private native long nCreate(String name); private static native long nCreate(String name); private static native long nGetNativeFinalizer(); private static native void nOutput(long renderNode); Loading @@ -853,6 +847,9 @@ public class RenderNode { // @CriticalNative methods /////////////////////////////////////////////////////////////////////////// @CriticalNative private static native boolean nIsValid(long renderNode); // Matrix @CriticalNative Loading
core/java/android/view/ThreadedRenderer.java +0 −9 Original line number Diff line number Diff line Loading @@ -496,15 +496,6 @@ public final class ThreadedRenderer { private static void destroyResources(View view) { view.destroyHardwareResources(); if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; int count = group.getChildCount(); for (int i = 0; i < count; i++) { destroyResources(group.getChildAt(i)); } } } /** Loading
core/java/android/view/View.java +8 −10 Original line number Diff line number Diff line Loading @@ -16613,11 +16613,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @CallSuper protected void destroyHardwareResources() { // Although the Layer will be destroyed by RenderNode, we want to release // the staging display list, which is also a signal to RenderNode that it's // safe to free its copy of the display list as it knows that we will // push an updated DisplayList if we try to draw again resetDisplayList(); if (mOverlay != null) { mOverlay.getOverlayView().destroyHardwareResources(); } if (mGhostView != null) { mGhostView.destroyHardwareResources(); } } /** Loading Loading @@ -16788,11 +16789,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void resetDisplayList() { if (mRenderNode.isValid()) { mRenderNode.discardDisplayList(); } if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { if (mBackgroundRenderNode != null) { mBackgroundRenderNode.discardDisplayList(); } }
core/java/android/view/ViewGroup.java +10 −0 Original line number Diff line number Diff line Loading @@ -4597,6 +4597,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager clearCachedLayoutMode(); } /** @hide */ @Override protected void destroyHardwareResources() { super.destroyHardwareResources(); int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).destroyHardwareResources(); } } /** * Adds a view during layout. This is useful if in your onLayout() method, * you need to add more views (as does the list view for example). Loading
core/jni/android_view_RenderNode.cpp +7 −70 Original line number Diff line number Diff line Loading @@ -43,57 +43,6 @@ using namespace uirenderer; ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \ : false) static JNIEnv* getenv(JavaVM* vm) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); } return env; } static jfieldID gRenderNode_validFieldID; class RenderNodeContext : public VirtualLightRefBase { public: RenderNodeContext(JNIEnv* env, jobject jobjRef) { env->GetJavaVM(&mVm); // This holds a weak ref because otherwise there's a cyclic global ref // with this holding a strong global ref to the view which holds // a strong ref to RenderNode which holds a strong ref to this. mWeakRef = env->NewWeakGlobalRef(jobjRef); } virtual ~RenderNodeContext() { JNIEnv* env = getenv(mVm); env->DeleteWeakGlobalRef(mWeakRef); } jobject acquireLocalRef(JNIEnv* env) { return env->NewLocalRef(mWeakRef); } private: JavaVM* mVm; jweak mWeakRef; }; // Called by ThreadedRenderer's JNI layer void onRenderNodeRemoved(JNIEnv* env, RenderNode* node) { auto context = reinterpret_cast<RenderNodeContext*>(node->getUserContext()); if (!context) return; jobject jnode = context->acquireLocalRef(env); if (!jnode) { // The owning node has been GC'd, release the context node->setUserContext(nullptr); return; } // Update the valid field, since native has already removed // the staging DisplayList env->SetBooleanField(jnode, gRenderNode_validFieldID, false); env->DeleteLocalRef(jnode); } // ---------------------------------------------------------------------------- // DisplayList view properties // ---------------------------------------------------------------------------- Loading @@ -108,8 +57,7 @@ static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlo return renderNode->getDebugSize(); } static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz, jstring name) { static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) { RenderNode* renderNode = new RenderNode(); renderNode->incStrong(0); if (name != NULL) { Loading @@ -117,7 +65,6 @@ static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz, renderNode->setName(textArray); env->ReleaseStringUTFChars(name, textArray); } renderNode->setUserContext(new RenderNodeContext(env, thiz)); return reinterpret_cast<jlong>(renderNode); } Loading @@ -132,22 +79,13 @@ static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env, static void android_view_RenderNode_setDisplayList(JNIEnv* env, jobject clazz, jlong renderNodePtr, jlong displayListPtr) { class RemovedObserver : public TreeObserver { public: virtual void onMaybeRemovedFromTree(RenderNode* node) override { maybeRemovedNodes.insert(sp<RenderNode>(node)); } std::set< sp<RenderNode> > maybeRemovedNodes; }; RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr); RemovedObserver observer; renderNode->setStagingDisplayList(newData, &observer); for (auto& node : observer.maybeRemovedNodes) { if (node->hasParents()) continue; onRenderNodeRemoved(env, node.get()); renderNode->setStagingDisplayList(newData); } static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) { return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid(); } // ---------------------------------------------------------------------------- Loading Loading @@ -621,6 +559,7 @@ static const JNINativeMethod gMethods[] = { // ---------------------------------------------------------------------------- // Critical JNI via @CriticalNative annotation in RenderNode.java // ---------------------------------------------------------------------------- { "nIsValid", "(J)Z", (void*) android_view_RenderNode_isValid }, { "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType }, { "nSetLayerPaint", "(JJ)Z", (void*) android_view_RenderNode_setLayerPaint }, { "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix }, Loading Loading @@ -691,8 +630,6 @@ int register_android_view_RenderNode(JNIEnv* env) { "updateWindowPosition_renderWorker", "(JIIII)V"); gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz, "windowPositionLost_uiRtSync", "(J)V"); clazz = FindClassOrDie(env, "android/view/RenderNode"); gRenderNode_validFieldID = GetFieldIDOrDie(env, clazz, "mValid", "Z"); return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } Loading