diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6b13a290b20ee..3ef6dfb27782a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1375,6 +1375,7 @@ public final class ViewRootImpl implements ViewParent, final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets; mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent, attrs.getTitle().toString()); + mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); updateColorModeIfNeeded(attrs.getColorMode()); updateForceDarkMode(); if (mAttachInfo.mThreadedRenderer != null) { @@ -1941,6 +1942,10 @@ public final class ViewRootImpl implements ViewParent, mBlastBufferQueue.destroy(); mBlastBufferQueue = null; } + + if (mAttachInfo.mThreadedRenderer != null) { + mAttachInfo.mThreadedRenderer.setSurfaceControl(null); + } } /** @@ -7645,6 +7650,9 @@ public final class ViewRootImpl implements ViewParent, mSurface.transferFrom(blastSurface); } } + if (mAttachInfo.mThreadedRenderer != null) { + mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); + } } else { destroySurface(); } diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index b70fa0e693c27..88cf96a9eb4ea 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -39,6 +39,7 @@ import android.view.IGraphicsStatsCallback; import android.view.NativeVectorDrawableAnimator; import android.view.PixelCopy; import android.view.Surface; +import android.view.SurfaceControl; import android.view.SurfaceHolder; import android.view.animation.AnimationUtils; @@ -313,6 +314,16 @@ public class HardwareRenderer { nSetSurface(mNativeProxy, surface, discardBuffer); } + /** + * Sets the SurfaceControl to be used internally inside render thread + * @hide + * @param surfaceControl The surface control to pass to render thread in hwui. + * If null, any previous references held in render thread will be discarded. + */ + public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) { + nSetSurfaceControl(mNativeProxy, surfaceControl != null ? surfaceControl.mNativeObject : 0); + } + /** * Sets the parameters that can be used to control a render request for a * {@link HardwareRenderer}. This is not thread-safe and must not be held on to for longer @@ -1216,6 +1227,8 @@ public class HardwareRenderer { private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer); + private static native void nSetSurfaceControl(long nativeProxy, long nativeSurfaceControl); + private static native boolean nPause(long nativeProxy); private static native void nSetStopped(long nativeProxy, boolean stopped); diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 4966bfa1c1e9a..df66981853bb1 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -189,6 +189,13 @@ static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz, } } +static void android_view_ThreadedRenderer_setSurfaceControl(JNIEnv* env, jobject clazz, + jlong proxyPtr, jlong surfaceControlPtr) { + RenderProxy* proxy = reinterpret_cast(proxyPtr); + ASurfaceControl* surfaceControl = reinterpret_cast(surfaceControlPtr); + proxy->setSurfaceControl(surfaceControl); +} + static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz, jlong proxyPtr) { RenderProxy* proxy = reinterpret_cast(proxyPtr); @@ -671,6 +678,8 @@ static const JNINativeMethod gMethods[] = { {"nSetName", "(JLjava/lang/String;)V", (void*)android_view_ThreadedRenderer_setName}, {"nSetSurface", "(JLandroid/view/Surface;Z)V", (void*)android_view_ThreadedRenderer_setSurface}, + {"nSetSurfaceControl", "(JJ)V", + (void*)android_view_ThreadedRenderer_setSurfaceControl}, {"nPause", "(J)Z", (void*)android_view_ThreadedRenderer_pause}, {"nSetStopped", "(JZ)V", (void*)android_view_ThreadedRenderer_setStopped}, {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha}, diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 65afcc3a2558b..9543d47640e69 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -133,6 +133,7 @@ void CanvasContext::removeRenderNode(RenderNode* node) { void CanvasContext::destroy() { stopDrawing(); setSurface(nullptr); + setSurfaceControl(nullptr); freePrefetchedLayers(); destroyHardwareResources(); mAnimationContext->destroy(); @@ -173,6 +174,19 @@ void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) { setupPipelineSurface(); } +void CanvasContext::setSurfaceControl(ASurfaceControl* surfaceControl) { + if (surfaceControl == mSurfaceControl) return; + + auto funcs = mRenderThread.getASurfaceControlFunctions(); + if (mSurfaceControl != nullptr) { + funcs.releaseFunc(mSurfaceControl); + } + mSurfaceControl = surfaceControl; + if (mSurfaceControl != nullptr) { + funcs.acquireFunc(mSurfaceControl); + } +} + void CanvasContext::setupPipelineSurface() { bool hasSurface = mRenderPipeline->setSurface( mNativeSurface ? mNativeSurface->getNativeWindow() : nullptr, mSwapBehavior); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index b31883b9ae943..917b00cb65917 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -112,6 +112,7 @@ public: void setSwapBehavior(SwapBehavior swapBehavior); void setSurface(ANativeWindow* window, bool enableTimeout = true); + void setSurfaceControl(ASurfaceControl* surfaceControl); bool pauseSurface(); void setStopped(bool stopped); bool hasSurface() const { return mNativeSurface.get(); } @@ -218,6 +219,9 @@ private: RenderThread& mRenderThread; std::unique_ptr mNativeSurface; + // The SurfaceControl reference is passed from ViewRootImpl, can be set to + // NULL to remove the reference + ASurfaceControl* mSurfaceControl = nullptr; // stopped indicates the CanvasContext will reject actual redraw operations, // and defer repaint until it is un-stopped bool mStopped = false; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 0ade8dde12eb9..e14842f89b615 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -84,6 +84,19 @@ void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) { }); } +void RenderProxy::setSurfaceControl(ASurfaceControl* surfaceControl) { + auto funcs = mRenderThread.getASurfaceControlFunctions(); + if (surfaceControl) { + funcs.acquireFunc(surfaceControl); + } + mRenderThread.queue().post([this, control = surfaceControl, funcs]() mutable { + mContext->setSurfaceControl(control); + if (control) { + funcs.releaseFunc(control); + } + }); +} + void RenderProxy::allocateBuffers() { mRenderThread.queue().post([=]() { mContext->allocateBuffers(); }); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index a4adb16a930e5..366d6b5a172c3 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "../FrameMetricsObserver.h" @@ -72,6 +73,7 @@ public: void setName(const char* name); void setSurface(ANativeWindow* window, bool enableTimeout = true); + void setSurfaceControl(ASurfaceControl* surfaceControl); void allocateBuffers(); bool pause(); void setStopped(bool stopped); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 7750a31b817f9..26101867c43f6 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,17 @@ static bool gHasRenderThreadInstance = false; static JVMAttachHook gOnStartHook = nullptr; +ASurfaceControlFunctions::ASurfaceControlFunctions() { + void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); + acquireFunc = (ASC_acquire) dlsym(handle_, "ASurfaceControl_acquire"); + LOG_ALWAYS_FATAL_IF(acquireFunc == nullptr, + "Failed to find required symbol ASurfaceControl_acquire!"); + + releaseFunc = (ASC_release) dlsym(handle_, "ASurfaceControl_release"); + LOG_ALWAYS_FATAL_IF(releaseFunc == nullptr, + "Failed to find required symbol ASurfaceControl_release!"); +} + void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) { RenderThread* rt = reinterpret_cast(data); int64_t vsyncId = AChoreographer_getVsyncId(rt->mChoreographer); diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 4fbb07168ac0b..bb7c5181e1121 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -78,6 +78,16 @@ struct VsyncSource { virtual ~VsyncSource() {} }; +typedef void (*ASC_acquire)(ASurfaceControl* control); +typedef void (*ASC_release)(ASurfaceControl* control); + +struct ASurfaceControlFunctions { + ASurfaceControlFunctions(); + + ASC_acquire acquireFunc; + ASC_release releaseFunc; +}; + class ChoreographerSource; class DummyVsyncSource; @@ -121,6 +131,10 @@ public: void preload(); + const ASurfaceControlFunctions& getASurfaceControlFunctions() { + return mASurfaceControlFunctions; + } + /** * isCurrent provides a way to query, if the caller is running on * the render thread. @@ -189,6 +203,8 @@ private: sk_sp mGrContext; CacheManager* mCacheManager; sp mVkManager; + + ASurfaceControlFunctions mASurfaceControlFunctions; }; } /* namespace renderthread */