1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #undef LOG_TAG
18 #define LOG_TAG "ThreadedRenderer"
19 #define ATRACE_TAG ATRACE_TAG_VIEW
20 
21 #include <FrameInfo.h>
22 #include <GraphicsJNI.h>
23 #include <Picture.h>
24 #include <Properties.h>
25 #include <RootRenderNode.h>
26 #include <SkImagePriv.h>
27 #include <SkSerialProcs.h>
28 #include <dlfcn.h>
29 #include <gui/TraceUtils.h>
30 #include <inttypes.h>
31 #include <media/NdkImage.h>
32 #include <media/NdkImageReader.h>
33 #include <nativehelper/JNIPlatformHelp.h>
34 #include <pipeline/skia/ShaderCache.h>
35 #include <private/EGL/cache.h>
36 #include <renderthread/CanvasContext.h>
37 #include <renderthread/RenderProxy.h>
38 #include <renderthread/RenderTask.h>
39 #include <renderthread/RenderThread.h>
40 #include <src/image/SkImage_Base.h>
41 #include <thread/CommonPool.h>
42 #include <utils/Color.h>
43 #include <utils/RefBase.h>
44 #include <utils/StrongPointer.h>
45 #include <utils/Timers.h>
46 
47 #include <algorithm>
48 #include <atomic>
49 #include <vector>
50 
51 #include "android_graphics_HardwareRendererObserver.h"
52 
53 namespace android {
54 
55 using namespace android::uirenderer;
56 using namespace android::uirenderer::renderthread;
57 
58 struct {
59     jclass clazz;
60     jmethodID invokePictureCapturedCallback;
61 } gHardwareRenderer;
62 
63 struct {
64     jmethodID onMergeTransaction;
65 } gASurfaceTransactionCallback;
66 
67 struct {
68     jmethodID prepare;
69 } gPrepareSurfaceControlForWebviewCallback;
70 
71 struct {
72     jmethodID onFrameDraw;
73 } gFrameDrawingCallback;
74 
75 struct {
76     jmethodID onFrameCommit;
77 } gFrameCommitCallback;
78 
79 struct {
80     jmethodID onFrameComplete;
81 } gFrameCompleteCallback;
82 
getenv(JavaVM * vm)83 static JNIEnv* getenv(JavaVM* vm) {
84     JNIEnv* env;
85     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
86         LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
87     }
88     return env;
89 }
90 
91 typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
92 ANW_fromSurface fromSurface;
93 
94 class JvmErrorReporter : public ErrorHandler {
95 public:
JvmErrorReporter(JNIEnv * env)96     JvmErrorReporter(JNIEnv* env) {
97         env->GetJavaVM(&mVm);
98     }
99 
onError(const std::string & message)100     virtual void onError(const std::string& message) override {
101         JNIEnv* env = getenv(mVm);
102         jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
103     }
104 private:
105     JavaVM* mVm;
106 };
107 
108 class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
109 public:
FrameCommitWrapper(JNIEnv * env,jobject jobject)110     explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
111         env->GetJavaVM(&mVm);
112         mObject = env->NewGlobalRef(jobject);
113         LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
114     }
115 
~FrameCommitWrapper()116     ~FrameCommitWrapper() { releaseObject(); }
117 
onFrameCommit(bool didProduceBuffer)118     void onFrameCommit(bool didProduceBuffer) {
119         if (mObject) {
120             ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
121             getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
122                                         didProduceBuffer);
123             releaseObject();
124         }
125     }
126 
127 private:
128     JavaVM* mVm;
129     jobject mObject;
130 
releaseObject()131     void releaseObject() {
132         if (mObject) {
133             getenv(mVm)->DeleteGlobalRef(mObject);
134             mObject = nullptr;
135         }
136     }
137 };
138 
android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv * env,jobject clazz)139 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
140     RenderProxy::rotateProcessStatsBuffer();
141 }
142 
android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv * env,jobject clazz,jint fd)143 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
144         jint fd) {
145     RenderProxy::setProcessStatsBuffer(fd);
146 }
147 
android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv * env,jobject clazz,jlong proxyPtr)148 static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
149         jlong proxyPtr) {
150     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
151     return proxy->getRenderThreadTid();
152 }
153 
android_view_ThreadedRenderer_createRootRenderNode(JNIEnv * env,jobject clazz)154 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
155     RootRenderNode* node = new RootRenderNode(std::make_unique<JvmErrorReporter>(env));
156     node->incStrong(0);
157     node->setName("RootRenderNode");
158     return reinterpret_cast<jlong>(node);
159 }
160 
android_view_ThreadedRenderer_createProxy(JNIEnv * env,jobject clazz,jboolean translucent,jlong rootRenderNodePtr)161 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
162         jboolean translucent, jlong rootRenderNodePtr) {
163     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
164     ContextFactoryImpl factory(rootRenderNode);
165     RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
166     return (jlong) proxy;
167 }
168 
android_view_ThreadedRenderer_deleteProxy(JNIEnv * env,jobject clazz,jlong proxyPtr)169 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
170         jlong proxyPtr) {
171     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
172     delete proxy;
173 }
174 
android_view_ThreadedRenderer_loadSystemProperties(JNIEnv * env,jobject clazz,jlong proxyPtr)175 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
176         jlong proxyPtr) {
177     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
178     return proxy->loadSystemProperties();
179 }
180 
android_view_ThreadedRenderer_setName(JNIEnv * env,jobject clazz,jlong proxyPtr,jstring jname)181 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
182         jlong proxyPtr, jstring jname) {
183     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
184     const char* name = env->GetStringUTFChars(jname, NULL);
185     proxy->setName(name);
186     env->ReleaseStringUTFChars(jname, name);
187 }
188 
android_view_ThreadedRenderer_setSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface,jboolean discardBuffer)189 static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
190         jlong proxyPtr, jobject jsurface, jboolean discardBuffer) {
191     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
192     ANativeWindow* window = nullptr;
193     if (jsurface) {
194         window = fromSurface(env, jsurface);
195     }
196     bool enableTimeout = true;
197     if (discardBuffer) {
198         // Currently only Surface#lockHardwareCanvas takes this path
199         enableTimeout = false;
200         proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
201     }
202     proxy->setSurface(window, enableTimeout);
203     if (window) {
204         ANativeWindow_release(window);
205     }
206 }
207 
android_view_ThreadedRenderer_setSurfaceControl(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong surfaceControlPtr)208 static void android_view_ThreadedRenderer_setSurfaceControl(JNIEnv* env, jobject clazz,
209         jlong proxyPtr, jlong surfaceControlPtr) {
210     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
211     ASurfaceControl* surfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControlPtr);
212     proxy->setSurfaceControl(surfaceControl);
213 }
214 
android_view_ThreadedRenderer_pause(JNIEnv * env,jobject clazz,jlong proxyPtr)215 static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
216         jlong proxyPtr) {
217     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
218     return proxy->pause();
219 }
220 
android_view_ThreadedRenderer_setStopped(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean stopped)221 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
222         jlong proxyPtr, jboolean stopped) {
223     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
224     proxy->setStopped(stopped);
225 }
226 
android_view_ThreadedRenderer_setLightAlpha(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat ambientShadowAlpha,jfloat spotShadowAlpha)227 static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
228         jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
229     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
230     proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
231 }
232 
android_view_ThreadedRenderer_setLightGeometry(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat lightX,jfloat lightY,jfloat lightZ,jfloat lightRadius)233 static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
234         jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
235     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
236     proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
237 }
238 
android_view_ThreadedRenderer_setOpaque(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean opaque)239 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
240         jlong proxyPtr, jboolean opaque) {
241     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
242     proxy->setOpaque(opaque);
243 }
244 
android_view_ThreadedRenderer_setColorMode(JNIEnv * env,jobject clazz,jlong proxyPtr,jint colorMode)245 static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz,
246         jlong proxyPtr, jint colorMode) {
247     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248     proxy->setColorMode(static_cast<ColorMode>(colorMode));
249 }
250 
android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat sdrWhitePoint)251 static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
252         jlong proxyPtr, jfloat sdrWhitePoint) {
253     Properties::defaultSdrWhitePoint = sdrWhitePoint;
254 }
255 
android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv * env,jobject clazz,jboolean jIsHighEndGfx)256 static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject clazz,
257         jboolean jIsHighEndGfx) {
258     Properties::setIsHighEndGfx(jIsHighEndGfx);
259 }
260 
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlongArray frameInfo,jint frameInfoSize)261 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
262         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
263     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
264                         "Mismatched size expectations, given %d expected %zu", frameInfoSize,
265                         UI_THREAD_FRAME_INFO_SIZE);
266     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
267     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
268     return proxy->syncAndDrawFrame();
269 }
270 
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong rootNodePtr)271 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
272         jlong proxyPtr, jlong rootNodePtr) {
273     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
274     rootRenderNode->destroy();
275     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
276     proxy->destroy();
277 }
278 
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)279 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
280         jlong rootNodePtr, jlong animatingNodePtr) {
281     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
282     RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
283     rootRenderNode->attachAnimatingNode(animatingNode);
284 }
285 
android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatorPtr)286 static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
287         jlong rootNodePtr, jlong animatorPtr) {
288     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
289     PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
290     rootRenderNode->addVectorDrawableAnimator(animator);
291 }
292 
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)293 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
294         jlong proxyPtr) {
295     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
296     DeferredLayerUpdater* layer = proxy->createTextureLayer();
297     return reinterpret_cast<jlong>(layer);
298 }
299 
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)300 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
301         jlong proxyPtr, jlong nodePtr) {
302     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
303     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
304     proxy->buildLayer(node);
305 }
306 
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jlong bitmapPtr)307 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
308         jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
309     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
310     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
311     SkBitmap bitmap;
312     bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
313     return proxy->copyLayerInto(layer, bitmap);
314 }
315 
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)316 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
317         jlong proxyPtr, jlong layerPtr) {
318     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
319     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
320     proxy->pushLayerUpdate(layer);
321 }
322 
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)323 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
324         jlong proxyPtr, jlong layerPtr) {
325     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
326     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
327     proxy->cancelLayerUpdate(layer);
328 }
329 
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)330 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
331         jlong proxyPtr, jlong layerPtr) {
332     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
333     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
334     proxy->detachSurfaceTexture(layer);
335 }
336 
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)337 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
338         jlong proxyPtr) {
339     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
340     proxy->destroyHardwareResources();
341 }
342 
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)343 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
344         jint level) {
345     RenderProxy::trimMemory(level);
346 }
347 
android_view_ThreadedRenderer_overrideProperty(JNIEnv * env,jobject clazz,jstring name,jstring value)348 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
349         jstring name, jstring value) {
350     const char* nameCharArray = env->GetStringUTFChars(name, NULL);
351     const char* valueCharArray = env->GetStringUTFChars(value, NULL);
352     RenderProxy::overrideProperty(nameCharArray, valueCharArray);
353     env->ReleaseStringUTFChars(name, nameCharArray);
354     env->ReleaseStringUTFChars(name, valueCharArray);
355 }
356 
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)357 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
358         jlong proxyPtr) {
359     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
360     proxy->fence();
361 }
362 
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)363 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
364         jlong proxyPtr) {
365     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
366     proxy->stopDrawing();
367 }
368 
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)369 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
370         jlong proxyPtr) {
371     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
372     proxy->notifyFramePending();
373 }
374 
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor,jint dumpFlags)375 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
376         jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
377     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
378     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
379     proxy->dumpProfileInfo(fd, dumpFlags);
380 }
381 
android_view_ThreadedRenderer_addRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr,jboolean placeFront)382 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
383         jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
384     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
385     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
386     proxy->addRenderNode(renderNode, placeFront);
387 }
388 
android_view_ThreadedRenderer_removeRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)389 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
390         jlong proxyPtr, jlong renderNodePtr) {
391     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
392     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
393     proxy->removeRenderNode(renderNode);
394 }
395 
android_view_ThreadedRendererd_drawRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)396 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
397         jlong proxyPtr, jlong renderNodePtr) {
398     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
399     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
400     proxy->drawRenderNode(renderNode);
401 }
402 
android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv * env,jobject clazz,jlong proxyPtr,jint left,jint top,jint right,jint bottom)403 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
404         jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
405     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
406     proxy->setContentDrawBounds(left, top, right, bottom);
407 }
408 
409 class JGlobalRefHolder {
410 public:
JGlobalRefHolder(JavaVM * vm,jobject object)411     JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
412 
~JGlobalRefHolder()413     virtual ~JGlobalRefHolder() {
414         getenv(mVm)->DeleteGlobalRef(mObject);
415         mObject = nullptr;
416     }
417 
object()418     jobject object() { return mObject; }
vm()419     JavaVM* vm() { return mVm; }
420 
421 private:
422     JGlobalRefHolder(const JGlobalRefHolder&) = delete;
423     void operator=(const JGlobalRefHolder&) = delete;
424 
425     JavaVM* mVm;
426     jobject mObject;
427 };
428 
429 class JWeakGlobalRefHolder {
430 public:
JWeakGlobalRefHolder(JavaVM * vm,jobject object)431     JWeakGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm) {
432         mWeakRef = getenv(vm)->NewWeakGlobalRef(object);
433     }
434 
~JWeakGlobalRefHolder()435     virtual ~JWeakGlobalRefHolder() {
436         if (mWeakRef != nullptr) getenv(mVm)->DeleteWeakGlobalRef(mWeakRef);
437         mWeakRef = nullptr;
438     }
439 
ref()440     jobject ref() { return mWeakRef; }
vm()441     JavaVM* vm() { return mVm; }
442 
443 private:
444     JWeakGlobalRefHolder(const JWeakGlobalRefHolder&) = delete;
445     void operator=(const JWeakGlobalRefHolder&) = delete;
446 
447     JavaVM* mVm;
448     jobject mWeakRef;
449 };
450 
451 using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>;
452 
453 struct PictureCaptureState {
454     // Each frame we move from the active map to the previous map, essentially an LRU of 1 frame
455     // This avoids repeated readbacks of the same image, but avoids artificially extending the
456     // lifetime of any particular image.
457     TextureMap mActiveMap;
458     TextureMap mPreviousActiveMap;
459 };
460 
461 // TODO: This & Multi-SKP & Single-SKP should all be de-duped into
462 // a single "make a SkPicture serailizable-safe" utility somewhere
463 class PictureWrapper : public Picture {
464 public:
PictureWrapper(sk_sp<SkPicture> && src,const std::shared_ptr<PictureCaptureState> & state)465     PictureWrapper(sk_sp<SkPicture>&& src, const std::shared_ptr<PictureCaptureState>& state)
466             : Picture(), mPicture(std::move(src)) {
467         ATRACE_NAME("Preparing SKP for capture");
468         // Move the active to previous active
469         state->mPreviousActiveMap = std::move(state->mActiveMap);
470         state->mActiveMap.clear();
471         SkSerialProcs tempProc;
472         tempProc.fImageCtx = state.get();
473         tempProc.fImageProc = collectNonTextureImagesProc;
474         auto ns = SkNullWStream();
475         mPicture->serialize(&ns, &tempProc);
476         state->mPreviousActiveMap.clear();
477 
478         // Now snapshot a copy of the active map so this PictureWrapper becomes self-sufficient
479         mTextureMap = state->mActiveMap;
480     }
481 
imageForCache(SkImage * img)482     static sk_sp<SkImage> imageForCache(SkImage* img) {
483         const SkBitmap* bitmap = as_IB(img)->onPeekBitmap();
484         // This is a mutable bitmap pretending to be an immutable SkImage. As we're going to
485         // actually cross thread boundaries here, make a copy so it's immutable proper
486         if (bitmap && !bitmap->isImmutable()) {
487             ATRACE_NAME("Copying mutable bitmap");
488             return SkImage::MakeFromBitmap(*bitmap);
489         }
490         if (img->isTextureBacked()) {
491             ATRACE_NAME("Readback of texture image");
492             return img->makeNonTextureImage();
493         }
494         SkPixmap pm;
495         if (img->isLazyGenerated() && !img->peekPixels(&pm)) {
496             ATRACE_NAME("Readback of HW bitmap");
497             // This is a hardware bitmap probably
498             SkBitmap bm;
499             if (!bm.tryAllocPixels(img->imageInfo())) {
500                 // Failed to allocate, just see what happens
501                 return sk_ref_sp(img);
502             }
503             if (RenderProxy::copyImageInto(sk_ref_sp(img), &bm)) {
504                 // Failed to readback
505                 return sk_ref_sp(img);
506             }
507             bm.setImmutable();
508             return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
509         }
510         return sk_ref_sp(img);
511     }
512 
collectNonTextureImagesProc(SkImage * img,void * ctx)513     static sk_sp<SkData> collectNonTextureImagesProc(SkImage* img, void* ctx) {
514         PictureCaptureState* context = reinterpret_cast<PictureCaptureState*>(ctx);
515         const uint32_t originalId = img->uniqueID();
516         auto it = context->mActiveMap.find(originalId);
517         if (it == context->mActiveMap.end()) {
518             auto pit = context->mPreviousActiveMap.find(originalId);
519             if (pit == context->mPreviousActiveMap.end()) {
520                 context->mActiveMap[originalId] = imageForCache(img);
521             } else {
522                 context->mActiveMap[originalId] = pit->second;
523             }
524         }
525         return SkData::MakeEmpty();
526     }
527 
serializeImage(SkImage * img,void * ctx)528     static sk_sp<SkData> serializeImage(SkImage* img, void* ctx) {
529         PictureWrapper* context = reinterpret_cast<PictureWrapper*>(ctx);
530         const uint32_t id = img->uniqueID();
531         auto iter = context->mTextureMap.find(id);
532         if (iter != context->mTextureMap.end()) {
533             img = iter->second.get();
534         }
535         return img->encodeToData();
536     }
537 
serialize(SkWStream * stream) const538     void serialize(SkWStream* stream) const override {
539         SkSerialProcs procs;
540         procs.fImageProc = serializeImage;
541         procs.fImageCtx = const_cast<PictureWrapper*>(this);
542         procs.fTypefaceProc = [](SkTypeface* tf, void* ctx) {
543             return tf->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
544         };
545         mPicture->serialize(stream, &procs);
546     }
547 
548 private:
549     sk_sp<SkPicture> mPicture;
550     TextureMap mTextureMap;
551 };
552 
android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject pictureCallback)553 static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* env,
554         jobject clazz, jlong proxyPtr, jobject pictureCallback) {
555     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
556     if (!pictureCallback) {
557         proxy->setPictureCapturedCallback(nullptr);
558     } else {
559         JavaVM* vm = nullptr;
560         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
561         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
562                 env->NewGlobalRef(pictureCallback));
563         auto pictureState = std::make_shared<PictureCaptureState>();
564         proxy->setPictureCapturedCallback([globalCallbackRef,
565                                            pictureState](sk_sp<SkPicture>&& picture) {
566             JNIEnv* env = getenv(globalCallbackRef->vm());
567             Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
568             env->CallStaticVoidMethod(gHardwareRenderer.clazz,
569                     gHardwareRenderer.invokePictureCapturedCallback,
570                     static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
571                     globalCallbackRef->object());
572         });
573     }
574 }
575 
android_view_ThreadedRenderer_setASurfaceTransactionCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject aSurfaceTransactionCallback)576 static void android_view_ThreadedRenderer_setASurfaceTransactionCallback(
577         JNIEnv* env, jobject clazz, jlong proxyPtr, jobject aSurfaceTransactionCallback) {
578     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
579     if (!aSurfaceTransactionCallback) {
580         proxy->setASurfaceTransactionCallback(nullptr);
581     } else {
582         JavaVM* vm = nullptr;
583         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
584         auto globalCallbackRef =
585                 std::make_shared<JWeakGlobalRefHolder>(vm, aSurfaceTransactionCallback);
586         proxy->setASurfaceTransactionCallback(
587                 [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) -> bool {
588                     JNIEnv* env = getenv(globalCallbackRef->vm());
589                     jobject localref = env->NewLocalRef(globalCallbackRef->ref());
590                     if (CC_UNLIKELY(!localref)) {
591                         return false;
592                     }
593                     jboolean ret = env->CallBooleanMethod(
594                             localref, gASurfaceTransactionCallback.onMergeTransaction,
595                             static_cast<jlong>(transObj), static_cast<jlong>(scObj),
596                             static_cast<jlong>(frameNr));
597                     env->DeleteLocalRef(localref);
598                     return ret;
599                 });
600     }
601 }
602 
android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)603 static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(
604         JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) {
605     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
606     if (!callback) {
607         proxy->setPrepareSurfaceControlForWebviewCallback(nullptr);
608     } else {
609         JavaVM* vm = nullptr;
610         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
611         auto globalCallbackRef =
612                 std::make_shared<JWeakGlobalRefHolder>(vm, callback);
613         proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
614             JNIEnv* env = getenv(globalCallbackRef->vm());
615             jobject localref = env->NewLocalRef(globalCallbackRef->ref());
616             if (CC_UNLIKELY(!localref)) {
617                 return;
618             }
619             env->CallVoidMethod(localref, gPrepareSurfaceControlForWebviewCallback.prepare);
620             env->DeleteLocalRef(localref);
621         });
622     }
623 }
624 
android_view_ThreadedRenderer_setFrameCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject frameCallback)625 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
626         jobject clazz, jlong proxyPtr, jobject frameCallback) {
627     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
628     if (!frameCallback) {
629         proxy->setFrameCallback(nullptr);
630     } else {
631         JavaVM* vm = nullptr;
632         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
633         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
634                 env->NewGlobalRef(frameCallback));
635         proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) {
636             JNIEnv* env = getenv(globalCallbackRef->vm());
637             env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
638                     static_cast<jlong>(frameNr));
639         });
640     }
641 }
642 
android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)643 static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz,
644                                                                  jlong proxyPtr, jobject callback) {
645     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
646     if (!callback) {
647         proxy->setFrameCommitCallback(nullptr);
648     } else {
649         sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback};
650         proxy->setFrameCommitCallback(
651                 [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
652     }
653 }
654 
android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)655 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
656         jobject clazz, jlong proxyPtr, jobject callback) {
657     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
658     if (!callback) {
659         proxy->setFrameCompleteCallback(nullptr);
660     } else {
661         RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
662         JavaVM* vm = nullptr;
663         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
664         auto globalCallbackRef =
665                 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
666         proxy->setFrameCompleteCallback([globalCallbackRef]() {
667             JNIEnv* env = getenv(globalCallbackRef->vm());
668             env->CallVoidMethod(globalCallbackRef->object(),
669                                 gFrameCompleteCallback.onFrameComplete);
670         });
671     }
672 }
673 
android_view_ThreadedRenderer_copySurfaceInto(JNIEnv * env,jobject clazz,jobject jsurface,jint left,jint top,jint right,jint bottom,jlong bitmapPtr)674 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
675         jobject clazz, jobject jsurface, jint left, jint top,
676         jint right, jint bottom, jlong bitmapPtr) {
677     SkBitmap bitmap;
678     bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
679     ANativeWindow* window = fromSurface(env, jsurface);
680     jint result = RenderProxy::copySurfaceInto(window, left, top, right, bottom, &bitmap);
681     ANativeWindow_release(window);
682     return result;
683 }
684 
685 class ContextFactory : public IContextFactory {
686 public:
createAnimationContext(renderthread::TimeLord & clock)687     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
688         return new AnimationContext(clock);
689     }
690 };
691 
android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv * env,jobject clazz,jlong renderNodePtr,jint jwidth,jint jheight)692 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
693         jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
694     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
695     if (jwidth <= 0 || jheight <= 0) {
696         ALOGW("Invalid width %d or height %d", jwidth, jheight);
697         return nullptr;
698     }
699 
700     uint32_t width = jwidth;
701     uint32_t height = jheight;
702 
703     // Create an ImageReader wired up to a BufferItemConsumer
704     AImageReader* rawReader;
705     constexpr auto usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
706                            AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
707                            AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
708     media_status_t result =
709             AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, usage, 2, &rawReader);
710     std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader,
711                                                                          AImageReader_delete);
712 
713     if (result != AMEDIA_OK) {
714         ALOGW("Error creating image reader!");
715         return nullptr;
716     }
717 
718     // Note that ownership of this window is maintained by AImageReader, so we
719     // shouldn't need to wrap around a smart pointer.
720     ANativeWindow* window;
721     result = AImageReader_getWindow(rawReader, &window);
722 
723     if (result != AMEDIA_OK) {
724         ALOGW("Error retrieving the native window!");
725         return nullptr;
726     }
727 
728     // Render into the surface
729     {
730         ContextFactory factory;
731         RenderProxy proxy{true, renderNode, &factory};
732         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
733         proxy.setSurface(window);
734         // Shadows can't be used via this interface, so just set the light source
735         // to all 0s.
736         proxy.setLightAlpha(0, 0);
737         proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
738         nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
739         UiFrameInfoBuilder(proxy.frameInfo())
740                 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
741                     UiFrameInfoBuilder::UNKNOWN_DEADLINE,
742                     UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL)
743                 .addFlag(FrameInfoFlags::SurfaceCanvas);
744         proxy.syncAndDrawFrame();
745     }
746 
747     AImage* rawImage;
748     result = AImageReader_acquireNextImage(rawReader, &rawImage);
749     std::unique_ptr<AImage, decltype(&AImage_delete)> image(rawImage, AImage_delete);
750     if (result != AMEDIA_OK) {
751         ALOGW("Error reading image: %d!", result);
752         return nullptr;
753     }
754 
755     AHardwareBuffer* buffer;
756     result = AImage_getHardwareBuffer(rawImage, &buffer);
757 
758     AHardwareBuffer_Desc desc;
759     AHardwareBuffer_describe(buffer, &desc);
760 
761     if (desc.width != width || desc.height != height) {
762         ALOGW("AHardwareBuffer size mismatch, got %dx%d expected %dx%d", desc.width, desc.height,
763               width, height);
764         // Continue I guess?
765     }
766 
767     sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(
768             static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window)));
769     if (cs == nullptr) {
770         // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure
771         // the returned bitmap has a color space.
772         cs = SkColorSpace::MakeSRGB();
773     }
774     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs);
775     return bitmap::createBitmap(env, bitmap.release(),
776             android::bitmap::kBitmapCreateFlag_Premultiplied);
777 }
778 
android_view_ThreadedRenderer_disableVsync(JNIEnv *,jclass)779 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
780     RenderProxy::disableVsync();
781 }
782 
android_view_ThreadedRenderer_setHighContrastText(JNIEnv *,jclass,jboolean enable)783 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
784     Properties::enableHighContrastText = enable;
785 }
786 
android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv *,jclass,jboolean enable)787 static void android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv*, jclass,
788         jboolean enable) {
789     Properties::enableRTAnimations = enable;
790 }
791 
android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv *,jclass,jboolean enable)792 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
793     Properties::debuggingEnabled = enable;
794 }
795 
android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv *,jclass,jboolean isolated)796 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
797     Properties::isolatedProcess = isolated;
798 }
799 
android_view_ThreadedRenderer_setContextPriority(JNIEnv *,jclass,jint contextPriority)800 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
801         jint contextPriority) {
802     Properties::contextPriority = contextPriority;
803 }
804 
android_view_ThreadedRenderer_allocateBuffers(JNIEnv * env,jobject clazz,jlong proxyPtr)805 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
806         jlong proxyPtr) {
807     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
808     proxy->allocateBuffers();
809 }
810 
android_view_ThreadedRenderer_setForceDark(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean enable)811 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
812         jlong proxyPtr, jboolean enable) {
813     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
814     proxy->setForceDark(enable);
815 }
816 
android_view_ThreadedRenderer_preload(JNIEnv *,jclass)817 static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
818     RenderProxy::preload();
819 }
820 
821 // Plumbs the display density down to DeviceInfo.
android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv *,jclass,jint densityDpi)822 static void android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv*, jclass, jint densityDpi) {
823     // Convert from dpi to density-independent pixels.
824     const float density = densityDpi / 160.0;
825     DeviceInfo::setDensity(density);
826 }
827 
android_view_ThreadedRenderer_initDisplayInfo(JNIEnv *,jclass,jint physicalWidth,jint physicalHeight,jfloat refreshRate,jint wideColorDataspace,jlong appVsyncOffsetNanos,jlong presentationDeadlineNanos)828 static void android_view_ThreadedRenderer_initDisplayInfo(JNIEnv*, jclass, jint physicalWidth,
829                                                           jint physicalHeight, jfloat refreshRate,
830                                                           jint wideColorDataspace,
831                                                           jlong appVsyncOffsetNanos,
832                                                           jlong presentationDeadlineNanos) {
833     DeviceInfo::setWidth(physicalWidth);
834     DeviceInfo::setHeight(physicalHeight);
835     DeviceInfo::setRefreshRate(refreshRate);
836     DeviceInfo::setWideColorDataspace(static_cast<ADataSpace>(wideColorDataspace));
837     DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
838     DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
839 }
840 
841 // ----------------------------------------------------------------------------
842 // HardwareRendererObserver
843 // ----------------------------------------------------------------------------
844 
android_view_ThreadedRenderer_addObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)845 static void android_view_ThreadedRenderer_addObserver(JNIEnv* env, jclass clazz,
846         jlong proxyPtr, jlong observerPtr) {
847     HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
848     renderthread::RenderProxy* renderProxy =
849             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
850 
851     renderProxy->addFrameMetricsObserver(observer);
852 }
853 
android_view_ThreadedRenderer_removeObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)854 static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass clazz,
855         jlong proxyPtr, jlong observerPtr) {
856     HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
857     renderthread::RenderProxy* renderProxy =
858             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
859 
860     renderProxy->removeFrameMetricsObserver(observer);
861 }
862 
863 // ----------------------------------------------------------------------------
864 // Shaders
865 // ----------------------------------------------------------------------------
866 
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath,jstring skiaDiskCachePath)867 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
868         jstring diskCachePath, jstring skiaDiskCachePath) {
869     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
870     android::egl_set_cache_filename(cacheArray);
871     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
872 
873     const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
874     uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
875     env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
876 }
877 
android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv * env,jobject clazz)878 static jboolean android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv* env, jobject clazz) {
879     // this value is valid only after loadSystemProperties() is called
880     return Properties::enableWebViewOverlays;
881 }
882 
883 // ----------------------------------------------------------------------------
884 // JNI Glue
885 // ----------------------------------------------------------------------------
886 
887 const char* const kClassPathName = "android/graphics/HardwareRenderer";
888 
889 static const JNINativeMethod gMethods[] = {
890         {"nRotateProcessStatsBuffer", "()V",
891          (void*)android_view_ThreadedRenderer_rotateProcessStatsBuffer},
892         {"nSetProcessStatsBuffer", "(I)V",
893          (void*)android_view_ThreadedRenderer_setProcessStatsBuffer},
894         {"nGetRenderThreadTid", "(J)I", (void*)android_view_ThreadedRenderer_getRenderThreadTid},
895         {"nCreateRootRenderNode", "()J", (void*)android_view_ThreadedRenderer_createRootRenderNode},
896         {"nCreateProxy", "(ZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
897         {"nDeleteProxy", "(J)V", (void*)android_view_ThreadedRenderer_deleteProxy},
898         {"nLoadSystemProperties", "(J)Z",
899          (void*)android_view_ThreadedRenderer_loadSystemProperties},
900         {"nSetName", "(JLjava/lang/String;)V", (void*)android_view_ThreadedRenderer_setName},
901         {"nSetSurface", "(JLandroid/view/Surface;Z)V",
902          (void*)android_view_ThreadedRenderer_setSurface},
903         {"nSetSurfaceControl", "(JJ)V", (void*)android_view_ThreadedRenderer_setSurfaceControl},
904         {"nPause", "(J)Z", (void*)android_view_ThreadedRenderer_pause},
905         {"nSetStopped", "(JZ)V", (void*)android_view_ThreadedRenderer_setStopped},
906         {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
907         {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
908         {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
909         {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
910         {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
911         {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx},
912         {"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
913         {"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
914         {"nRegisterAnimatingRenderNode", "(JJ)V",
915          (void*)android_view_ThreadedRenderer_registerAnimatingRenderNode},
916         {"nRegisterVectorDrawableAnimator", "(JJ)V",
917          (void*)android_view_ThreadedRenderer_registerVectorDrawableAnimator},
918         {"nCreateTextureLayer", "(J)J", (void*)android_view_ThreadedRenderer_createTextureLayer},
919         {"nBuildLayer", "(JJ)V", (void*)android_view_ThreadedRenderer_buildLayer},
920         {"nCopyLayerInto", "(JJJ)Z", (void*)android_view_ThreadedRenderer_copyLayerInto},
921         {"nPushLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_pushLayerUpdate},
922         {"nCancelLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_cancelLayerUpdate},
923         {"nDetachSurfaceTexture", "(JJ)V",
924          (void*)android_view_ThreadedRenderer_detachSurfaceTexture},
925         {"nDestroyHardwareResources", "(J)V",
926          (void*)android_view_ThreadedRenderer_destroyHardwareResources},
927         {"nTrimMemory", "(I)V", (void*)android_view_ThreadedRenderer_trimMemory},
928         {"nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
929          (void*)android_view_ThreadedRenderer_overrideProperty},
930         {"nFence", "(J)V", (void*)android_view_ThreadedRenderer_fence},
931         {"nStopDrawing", "(J)V", (void*)android_view_ThreadedRenderer_stopDrawing},
932         {"nNotifyFramePending", "(J)V", (void*)android_view_ThreadedRenderer_notifyFramePending},
933         {"nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V",
934          (void*)android_view_ThreadedRenderer_dumpProfileInfo},
935         {"setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V",
936          (void*)android_view_ThreadedRenderer_setupShadersDiskCache},
937         {"nAddRenderNode", "(JJZ)V", (void*)android_view_ThreadedRenderer_addRenderNode},
938         {"nRemoveRenderNode", "(JJ)V", (void*)android_view_ThreadedRenderer_removeRenderNode},
939         {"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode},
940         {"nSetContentDrawBounds", "(JIIII)V",
941          (void*)android_view_ThreadedRenderer_setContentDrawBounds},
942         {"nSetPictureCaptureCallback",
943          "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V",
944          (void*)android_view_ThreadedRenderer_setPictureCapturedCallbackJNI},
945         {"nSetASurfaceTransactionCallback",
946          "(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V",
947          (void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback},
948         {"nSetPrepareSurfaceControlForWebviewCallback",
949          "(JLandroid/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback;)V",
950          (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
951         {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
952          (void*)android_view_ThreadedRenderer_setFrameCallback},
953         {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
954          (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
955         {"nSetFrameCompleteCallback",
956          "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
957          (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
958         {"nAddObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_addObserver},
959         {"nRemoveObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_removeObserver},
960         {"nCopySurfaceInto", "(Landroid/view/Surface;IIIIJ)I",
961          (void*)android_view_ThreadedRenderer_copySurfaceInto},
962         {"nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
963          (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode},
964         {"disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync},
965         {"nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText},
966         {"nHackySetRTAnimationsEnabled", "(Z)V",
967          (void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled},
968         {"nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled},
969         {"nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess},
970         {"nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority},
971         {"nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers},
972         {"nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark},
973         {"nSetDisplayDensityDpi", "(I)V",
974          (void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
975         {"nInitDisplayInfo", "(IIFIJJ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
976         {"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
977         {"isWebViewOverlaysEnabled", "()Z",
978          (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
979 };
980 
981 static JavaVM* mJvm = nullptr;
982 
attachRenderThreadToJvm(const char * name)983 static void attachRenderThreadToJvm(const char* name) {
984     LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??");
985 
986     JavaVMAttachArgs args;
987     args.version = JNI_VERSION_1_4;
988     args.name = name;
989     args.group = NULL;
990     JNIEnv* env;
991     mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args);
992 }
993 
register_android_view_ThreadedRenderer(JNIEnv * env)994 int register_android_view_ThreadedRenderer(JNIEnv* env) {
995     env->GetJavaVM(&mJvm);
996     RenderThread::setOnStartHook(&attachRenderThreadToJvm);
997 
998     jclass hardwareRenderer = FindClassOrDie(env,
999             "android/graphics/HardwareRenderer");
1000     gHardwareRenderer.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(hardwareRenderer));
1001     gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
1002             "invokePictureCapturedCallback",
1003             "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
1004 
1005     jclass aSurfaceTransactionCallbackClass =
1006             FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
1007     gASurfaceTransactionCallback.onMergeTransaction =
1008             GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)Z");
1009 
1010     jclass prepareSurfaceControlForWebviewCallbackClass = FindClassOrDie(
1011             env, "android/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback");
1012     gPrepareSurfaceControlForWebviewCallback.prepare =
1013             GetMethodIDOrDie(env, prepareSurfaceControlForWebviewCallbackClass, "prepare", "()V");
1014 
1015     jclass frameCallbackClass = FindClassOrDie(env,
1016             "android/graphics/HardwareRenderer$FrameDrawingCallback");
1017     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
1018             "onFrameDraw", "(J)V");
1019 
1020     jclass frameCommitClass =
1021             FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
1022     gFrameCommitCallback.onFrameCommit =
1023             GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");
1024 
1025     jclass frameCompleteClass = FindClassOrDie(env,
1026             "android/graphics/HardwareRenderer$FrameCompleteCallback");
1027     gFrameCompleteCallback.onFrameComplete =
1028             GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");
1029 
1030     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
1031     fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
1032     LOG_ALWAYS_FATAL_IF(fromSurface == nullptr,
1033                         "Failed to find required symbol ANativeWindow_fromSurface!");
1034 
1035     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1036 }
1037 
1038 }; // namespace android
1039