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 <SkBitmap.h>
27 #include <SkColorSpace.h>
28 #include <SkData.h>
29 #include <SkImage.h>
30 #include <SkImagePriv.h>
31 #include <SkPicture.h>
32 #include <SkPixmap.h>
33 #include <SkSerialProcs.h>
34 #include <SkStream.h>
35 #include <SkTypeface.h>
36 #include <dlfcn.h>
37 #include <gui/TraceUtils.h>
38 #include <inttypes.h>
39 #include <media/NdkImage.h>
40 #include <media/NdkImageReader.h>
41 #include <nativehelper/JNIPlatformHelp.h>
42 #include <pipeline/skia/ShaderCache.h>
43 #include <private/EGL/cache.h>
44 #include <renderthread/CanvasContext.h>
45 #include <renderthread/RenderProxy.h>
46 #include <renderthread/RenderTask.h>
47 #include <renderthread/RenderThread.h>
48 #include <src/image/SkImage_Base.h>
49 #include <thread/CommonPool.h>
50 #include <utils/Color.h>
51 #include <utils/RefBase.h>
52 #include <utils/StrongPointer.h>
53 #include <utils/Timers.h>
54 
55 #include <algorithm>
56 #include <atomic>
57 #include <vector>
58 
59 #include "JvmErrorReporter.h"
60 #include "android_graphics_HardwareRendererObserver.h"
61 
62 namespace android {
63 
64 using namespace android::uirenderer;
65 using namespace android::uirenderer::renderthread;
66 
67 struct {
68     jclass clazz;
69     jmethodID invokePictureCapturedCallback;
70 } gHardwareRenderer;
71 
72 struct {
73     jmethodID onMergeTransaction;
74 } gASurfaceTransactionCallback;
75 
76 struct {
77     jmethodID prepare;
78 } gPrepareSurfaceControlForWebviewCallback;
79 
80 struct {
81     jmethodID onFrameDraw;
82 } gFrameDrawingCallback;
83 
84 struct {
85     jmethodID onFrameCommit;
86 } gFrameCommitCallback;
87 
88 struct {
89     jmethodID onFrameComplete;
90 } gFrameCompleteCallback;
91 
92 struct {
93     jmethodID onCopyFinished;
94     jmethodID getDestinationBitmap;
95 } gCopyRequest;
96 
getenv(JavaVM * vm)97 static JNIEnv* getenv(JavaVM* vm) {
98     JNIEnv* env;
99     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
100         LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
101     }
102     return env;
103 }
104 
105 typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
106 ANW_fromSurface fromSurface;
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 jfloat android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz, jlong proxyPtr,
246                                                          jint colorMode) {
247     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248     return proxy->setColorMode(static_cast<ColorMode>(colorMode));
249 }
250 
android_view_ThreadedRenderer_setTargetSdrHdrRatio(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat ratio)251 static void android_view_ThreadedRenderer_setTargetSdrHdrRatio(JNIEnv* env, jobject clazz,
252                                                                jlong proxyPtr, jfloat ratio) {
253     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
254     return proxy->setRenderSdrHdrRatio(ratio);
255 }
256 
android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat sdrWhitePoint)257 static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
258         jlong proxyPtr, jfloat sdrWhitePoint) {
259     Properties::defaultSdrWhitePoint = sdrWhitePoint;
260 }
261 
android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv * env,jobject clazz,jboolean jIsHighEndGfx)262 static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject clazz,
263         jboolean jIsHighEndGfx) {
264     Properties::setIsHighEndGfx(jIsHighEndGfx);
265 }
266 
android_view_ThreadedRenderer_setIsLowRam(JNIEnv * env,jobject clazz,jboolean isLowRam)267 static void android_view_ThreadedRenderer_setIsLowRam(JNIEnv* env, jobject clazz,
268                                                       jboolean isLowRam) {
269     Properties::setIsLowRam(isLowRam);
270 }
271 
android_view_ThreadedRenderer_setIsSystemOrPersistent(JNIEnv * env,jobject clazz,jboolean isSystemOrPersistent)272 static void android_view_ThreadedRenderer_setIsSystemOrPersistent(JNIEnv* env, jobject clazz,
273                                                                   jboolean isSystemOrPersistent) {
274     Properties::setIsSystemOrPersistent(isSystemOrPersistent);
275 }
276 
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlongArray frameInfo,jint frameInfoSize)277 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
278                                                           jlong proxyPtr, jlongArray frameInfo,
279                                                           jint frameInfoSize) {
280     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
281                         "Mismatched size expectations, given %d expected %zu", frameInfoSize,
282                         UI_THREAD_FRAME_INFO_SIZE);
283     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
284     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
285     return proxy->syncAndDrawFrame();
286 }
287 
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong rootNodePtr)288 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
289         jlong proxyPtr, jlong rootNodePtr) {
290     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
291     rootRenderNode->destroy();
292     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
293     proxy->destroy();
294 }
295 
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)296 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
297         jlong rootNodePtr, jlong animatingNodePtr) {
298     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
299     RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
300     rootRenderNode->attachAnimatingNode(animatingNode);
301 }
302 
android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatorPtr)303 static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
304         jlong rootNodePtr, jlong animatorPtr) {
305     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
306     PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
307     rootRenderNode->addVectorDrawableAnimator(animator);
308 }
309 
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)310 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
311         jlong proxyPtr) {
312     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
313     DeferredLayerUpdater* layer = proxy->createTextureLayer();
314     return reinterpret_cast<jlong>(layer);
315 }
316 
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)317 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
318         jlong proxyPtr, jlong nodePtr) {
319     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
320     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
321     proxy->buildLayer(node);
322 }
323 
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jlong bitmapPtr)324 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
325         jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
326     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
327     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
328     SkBitmap bitmap;
329     bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
330     return proxy->copyLayerInto(layer, bitmap);
331 }
332 
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)333 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
334         jlong proxyPtr, jlong layerPtr) {
335     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
336     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
337     proxy->pushLayerUpdate(layer);
338 }
339 
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)340 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
341         jlong proxyPtr, jlong layerPtr) {
342     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
343     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
344     proxy->cancelLayerUpdate(layer);
345 }
346 
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)347 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
348         jlong proxyPtr, jlong layerPtr) {
349     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
350     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
351     proxy->detachSurfaceTexture(layer);
352 }
353 
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)354 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
355         jlong proxyPtr) {
356     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
357     proxy->destroyHardwareResources();
358 }
359 
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)360 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
361         jint level) {
362     RenderProxy::trimMemory(level);
363 }
364 
android_view_ThreadedRenderer_trimCaches(JNIEnv * env,jobject clazz,jint level)365 static void android_view_ThreadedRenderer_trimCaches(JNIEnv* env, jobject clazz, jint level) {
366     RenderProxy::trimCaches(level);
367 }
368 
android_view_ThreadedRenderer_overrideProperty(JNIEnv * env,jobject clazz,jstring name,jstring value)369 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
370         jstring name, jstring value) {
371     const char* nameCharArray = env->GetStringUTFChars(name, NULL);
372     const char* valueCharArray = env->GetStringUTFChars(value, NULL);
373     RenderProxy::overrideProperty(nameCharArray, valueCharArray);
374     env->ReleaseStringUTFChars(name, nameCharArray);
375     env->ReleaseStringUTFChars(name, valueCharArray);
376 }
377 
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)378 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
379         jlong proxyPtr) {
380     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
381     proxy->fence();
382 }
383 
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)384 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
385         jlong proxyPtr) {
386     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
387     proxy->stopDrawing();
388 }
389 
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)390 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
391         jlong proxyPtr) {
392     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
393     proxy->notifyFramePending();
394 }
395 
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor,jint dumpFlags)396 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
397         jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
398     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
399     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
400     proxy->dumpProfileInfo(fd, dumpFlags);
401 }
402 
android_view_ThreadedRenderer_dumpGlobalProfileInfo(JNIEnv * env,jobject clazz,jobject javaFileDescriptor,jint dumpFlags)403 static void android_view_ThreadedRenderer_dumpGlobalProfileInfo(JNIEnv* env, jobject clazz,
404                                                                 jobject javaFileDescriptor,
405                                                                 jint dumpFlags) {
406     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
407     RenderProxy::dumpGraphicsMemory(fd, true, dumpFlags & DumpFlags::Reset);
408 }
409 
android_view_ThreadedRenderer_addRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr,jboolean placeFront)410 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
411         jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
412     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
413     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
414     proxy->addRenderNode(renderNode, placeFront);
415 }
416 
android_view_ThreadedRenderer_removeRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)417 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
418         jlong proxyPtr, jlong renderNodePtr) {
419     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
420     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
421     proxy->removeRenderNode(renderNode);
422 }
423 
android_view_ThreadedRendererd_drawRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)424 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
425         jlong proxyPtr, jlong renderNodePtr) {
426     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
427     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
428     proxy->drawRenderNode(renderNode);
429 }
430 
android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv * env,jobject clazz,jlong proxyPtr,jint left,jint top,jint right,jint bottom)431 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
432         jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
433     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
434     proxy->setContentDrawBounds(left, top, right, bottom);
435 }
436 
android_view_ThreadedRenderer_forceDrawNextFrame(JNIEnv * env,jobject clazz,jlong proxyPtr)437 static void android_view_ThreadedRenderer_forceDrawNextFrame(JNIEnv* env, jobject clazz,
438                                                              jlong proxyPtr) {
439     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
440     proxy->forceDrawNextFrame();
441 }
442 
443 using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>;
444 
445 struct PictureCaptureState {
446     // Each frame we move from the active map to the previous map, essentially an LRU of 1 frame
447     // This avoids repeated readbacks of the same image, but avoids artificially extending the
448     // lifetime of any particular image.
449     TextureMap mActiveMap;
450     TextureMap mPreviousActiveMap;
451 };
452 
453 // TODO: This & Multi-SKP & Single-SKP should all be de-duped into
454 // a single "make a SkPicture serializable-safe" utility somewhere
455 class PictureWrapper : public Picture {
456 public:
PictureWrapper(sk_sp<SkPicture> && src,const std::shared_ptr<PictureCaptureState> & state)457     PictureWrapper(sk_sp<SkPicture>&& src, const std::shared_ptr<PictureCaptureState>& state)
458             : Picture(), mPicture(std::move(src)) {
459         ATRACE_NAME("Preparing SKP for capture");
460         // Move the active to previous active
461         state->mPreviousActiveMap = std::move(state->mActiveMap);
462         state->mActiveMap.clear();
463         SkSerialProcs tempProc;
464         tempProc.fImageCtx = state.get();
465         tempProc.fImageProc = collectNonTextureImagesProc;
466         auto ns = SkNullWStream();
467         mPicture->serialize(&ns, &tempProc);
468         state->mPreviousActiveMap.clear();
469 
470         // Now snapshot a copy of the active map so this PictureWrapper becomes self-sufficient
471         mTextureMap = state->mActiveMap;
472     }
473 
imageForCache(SkImage * img)474     static sk_sp<SkImage> imageForCache(SkImage* img) {
475         const SkBitmap* bitmap = as_IB(img)->onPeekBitmap();
476         // This is a mutable bitmap pretending to be an immutable SkImage. As we're going to
477         // actually cross thread boundaries here, make a copy so it's immutable proper
478         if (bitmap && !bitmap->isImmutable()) {
479             ATRACE_NAME("Copying mutable bitmap");
480             return SkImage::MakeFromBitmap(*bitmap);
481         }
482         if (img->isTextureBacked()) {
483             ATRACE_NAME("Readback of texture image");
484             return img->makeNonTextureImage();
485         }
486         SkPixmap pm;
487         if (img->isLazyGenerated() && !img->peekPixels(&pm)) {
488             ATRACE_NAME("Readback of HW bitmap");
489             // This is a hardware bitmap probably
490             SkBitmap bm;
491             if (!bm.tryAllocPixels(img->imageInfo())) {
492                 // Failed to allocate, just see what happens
493                 return sk_ref_sp(img);
494             }
495             if (RenderProxy::copyImageInto(sk_ref_sp(img), &bm)) {
496                 // Failed to readback
497                 return sk_ref_sp(img);
498             }
499             bm.setImmutable();
500             return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
501         }
502         return sk_ref_sp(img);
503     }
504 
collectNonTextureImagesProc(SkImage * img,void * ctx)505     static sk_sp<SkData> collectNonTextureImagesProc(SkImage* img, void* ctx) {
506         PictureCaptureState* context = reinterpret_cast<PictureCaptureState*>(ctx);
507         const uint32_t originalId = img->uniqueID();
508         auto it = context->mActiveMap.find(originalId);
509         if (it == context->mActiveMap.end()) {
510             auto pit = context->mPreviousActiveMap.find(originalId);
511             if (pit == context->mPreviousActiveMap.end()) {
512                 context->mActiveMap[originalId] = imageForCache(img);
513             } else {
514                 context->mActiveMap[originalId] = pit->second;
515             }
516         }
517         return SkData::MakeEmpty();
518     }
519 
serializeImage(SkImage * img,void * ctx)520     static sk_sp<SkData> serializeImage(SkImage* img, void* ctx) {
521         PictureWrapper* context = reinterpret_cast<PictureWrapper*>(ctx);
522         const uint32_t id = img->uniqueID();
523         auto iter = context->mTextureMap.find(id);
524         if (iter != context->mTextureMap.end()) {
525             img = iter->second.get();
526         }
527         return img->encodeToData();
528     }
529 
serialize(SkWStream * stream) const530     void serialize(SkWStream* stream) const override {
531         SkSerialProcs procs;
532         procs.fImageProc = serializeImage;
533         procs.fImageCtx = const_cast<PictureWrapper*>(this);
534         procs.fTypefaceProc = [](SkTypeface* tf, void* ctx) {
535             return tf->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
536         };
537         mPicture->serialize(stream, &procs);
538     }
539 
540 private:
541     sk_sp<SkPicture> mPicture;
542     TextureMap mTextureMap;
543 };
544 
android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject pictureCallback)545 static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* env,
546         jobject clazz, jlong proxyPtr, jobject pictureCallback) {
547     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
548     if (!pictureCallback) {
549         proxy->setPictureCapturedCallback(nullptr);
550     } else {
551         JavaVM* vm = nullptr;
552         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
553         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
554                 env->NewGlobalRef(pictureCallback));
555         auto pictureState = std::make_shared<PictureCaptureState>();
556         proxy->setPictureCapturedCallback([globalCallbackRef,
557                                            pictureState](sk_sp<SkPicture>&& picture) {
558             Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
559             globalCallbackRef->env()->CallStaticVoidMethod(
560                     gHardwareRenderer.clazz, gHardwareRenderer.invokePictureCapturedCallback,
561                     static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
562                     globalCallbackRef->object());
563         });
564     }
565 }
566 
android_view_ThreadedRenderer_setASurfaceTransactionCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject aSurfaceTransactionCallback)567 static void android_view_ThreadedRenderer_setASurfaceTransactionCallback(
568         JNIEnv* env, jobject clazz, jlong proxyPtr, jobject aSurfaceTransactionCallback) {
569     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
570     if (!aSurfaceTransactionCallback) {
571         proxy->setASurfaceTransactionCallback(nullptr);
572     } else {
573         JavaVM* vm = nullptr;
574         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
575         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(
576                 vm, env->NewGlobalRef(aSurfaceTransactionCallback));
577         proxy->setASurfaceTransactionCallback([globalCallbackRef](int64_t transObj, int64_t scObj,
578                                                                   int64_t frameNr) -> bool {
579             jboolean ret = globalCallbackRef->env()->CallBooleanMethod(
580                     globalCallbackRef->object(), gASurfaceTransactionCallback.onMergeTransaction,
581                     static_cast<jlong>(transObj), static_cast<jlong>(scObj),
582                     static_cast<jlong>(frameNr));
583             return ret;
584         });
585     }
586 }
587 
android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)588 static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(
589         JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) {
590     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
591     if (!callback) {
592         proxy->setPrepareSurfaceControlForWebviewCallback(nullptr);
593     } else {
594         JavaVM* vm = nullptr;
595         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
596         auto globalCallbackRef =
597                 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
598         proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
599             globalCallbackRef->env()->CallVoidMethod(
600                     globalCallbackRef->object(), gPrepareSurfaceControlForWebviewCallback.prepare);
601         });
602     }
603 }
604 
android_view_ThreadedRenderer_setFrameCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject frameCallback)605 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
606         jobject clazz, jlong proxyPtr, jobject frameCallback) {
607     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
608     if (!frameCallback) {
609         proxy->setFrameCallback(nullptr);
610     } else {
611         JavaVM* vm = nullptr;
612         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
613         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
614                 env->NewGlobalRef(frameCallback));
615         proxy->setFrameCallback([globalCallbackRef](int32_t syncResult,
616                                                     int64_t frameNr) -> std::function<void(bool)> {
617             JNIEnv* env = globalCallbackRef->env();
618             ScopedLocalRef<jobject> frameCommitCallback(
619                     env, env->CallObjectMethod(
620                                  globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
621                                  static_cast<jint>(syncResult), static_cast<jlong>(frameNr)));
622             if (frameCommitCallback == nullptr) {
623                 return nullptr;
624             }
625             sp<FrameCommitWrapper> wrapper =
626                     sp<FrameCommitWrapper>::make(env, frameCommitCallback.get());
627             return [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); };
628         });
629     }
630 }
631 
android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)632 static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz,
633                                                                  jlong proxyPtr, jobject callback) {
634     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
635     if (!callback) {
636         proxy->setFrameCommitCallback(nullptr);
637     } else {
638         sp<FrameCommitWrapper> wrapper = sp<FrameCommitWrapper>::make(env, callback);
639         proxy->setFrameCommitCallback(
640                 [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
641     }
642 }
643 
android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)644 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
645         jobject clazz, jlong proxyPtr, jobject callback) {
646     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
647     if (!callback) {
648         proxy->setFrameCompleteCallback(nullptr);
649     } else {
650         RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
651         JavaVM* vm = nullptr;
652         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
653         auto globalCallbackRef =
654                 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
655         proxy->setFrameCompleteCallback([globalCallbackRef]() {
656             globalCallbackRef->env()->CallVoidMethod(globalCallbackRef->object(),
657                                                      gFrameCompleteCallback.onFrameComplete);
658         });
659     }
660 }
661 
662 class CopyRequestAdapter : public CopyRequest {
663 public:
CopyRequestAdapter(JavaVM * vm,jobject jCopyRequest,Rect srcRect)664     CopyRequestAdapter(JavaVM* vm, jobject jCopyRequest, Rect srcRect)
665             : CopyRequest(srcRect), mRefHolder(vm, jCopyRequest) {}
666 
getDestinationBitmap(int srcWidth,int srcHeight)667     virtual SkBitmap getDestinationBitmap(int srcWidth, int srcHeight) override {
668         jlong bitmapPtr = mRefHolder.env()->CallLongMethod(
669                 mRefHolder.object(), gCopyRequest.getDestinationBitmap, srcWidth, srcHeight);
670         SkBitmap bitmap;
671         bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
672         return bitmap;
673     }
674 
onCopyFinished(CopyResult result)675     virtual void onCopyFinished(CopyResult result) override {
676         mRefHolder.env()->CallVoidMethod(mRefHolder.object(), gCopyRequest.onCopyFinished,
677                                          static_cast<jint>(result));
678     }
679 
680 private:
681     JGlobalRefHolder mRefHolder;
682 };
683 
android_view_ThreadedRenderer_copySurfaceInto(JNIEnv * env,jobject clazz,jobject jsurface,jint left,jint top,jint right,jint bottom,jobject jCopyRequest)684 static void android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, jobject clazz,
685                                                           jobject jsurface, jint left, jint top,
686                                                           jint right, jint bottom,
687                                                           jobject jCopyRequest) {
688     JavaVM* vm = nullptr;
689     LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
690     auto copyRequest = std::make_shared<CopyRequestAdapter>(vm, env->NewGlobalRef(jCopyRequest),
691                                                             Rect(left, top, right, bottom));
692     ANativeWindow* window = fromSurface(env, jsurface);
693     RenderProxy::copySurfaceInto(window, std::move(copyRequest));
694     ANativeWindow_release(window);
695 }
696 
697 class ContextFactory : public IContextFactory {
698 public:
createAnimationContext(renderthread::TimeLord & clock)699     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
700         return new AnimationContext(clock);
701     }
702 };
703 
android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv * env,jobject clazz,jlong renderNodePtr,jint jwidth,jint jheight)704 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
705         jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
706     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
707     if (jwidth <= 0 || jheight <= 0) {
708         ALOGW("Invalid width %d or height %d", jwidth, jheight);
709         return nullptr;
710     }
711 
712     uint32_t width = jwidth;
713     uint32_t height = jheight;
714 
715     // Create an ImageReader wired up to a BufferItemConsumer
716     AImageReader* rawReader;
717     constexpr auto usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
718                            AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
719                            AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
720     media_status_t result =
721             AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, usage, 2, &rawReader);
722     std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader,
723                                                                          AImageReader_delete);
724 
725     if (result != AMEDIA_OK) {
726         ALOGW("Error creating image reader!");
727         return nullptr;
728     }
729 
730     // Note that ownership of this window is maintained by AImageReader, so we
731     // shouldn't need to wrap around a smart pointer.
732     ANativeWindow* window;
733     result = AImageReader_getWindow(rawReader, &window);
734 
735     if (result != AMEDIA_OK) {
736         ALOGW("Error retrieving the native window!");
737         return nullptr;
738     }
739 
740     // Render into the surface
741     {
742         ContextFactory factory;
743         RenderProxy proxy{true, renderNode, &factory};
744         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
745         proxy.setSurface(window);
746         // Shadows can't be used via this interface, so just set the light source
747         // to all 0s.
748         proxy.setLightAlpha(0, 0);
749         proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
750         nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
751         UiFrameInfoBuilder(proxy.frameInfo())
752                 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
753                     UiFrameInfoBuilder::UNKNOWN_DEADLINE,
754                     UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL)
755                 .addFlag(FrameInfoFlags::SurfaceCanvas);
756         proxy.syncAndDrawFrame();
757     }
758 
759     AImage* rawImage;
760     result = AImageReader_acquireNextImage(rawReader, &rawImage);
761     std::unique_ptr<AImage, decltype(&AImage_delete)> image(rawImage, AImage_delete);
762     if (result != AMEDIA_OK) {
763         ALOGW("Error reading image: %d!", result);
764         return nullptr;
765     }
766 
767     AHardwareBuffer* buffer;
768     result = AImage_getHardwareBuffer(rawImage, &buffer);
769 
770     AHardwareBuffer_Desc desc;
771     AHardwareBuffer_describe(buffer, &desc);
772 
773     if (desc.width != width || desc.height != height) {
774         ALOGW("AHardwareBuffer size mismatch, got %dx%d expected %dx%d", desc.width, desc.height,
775               width, height);
776         // Continue I guess?
777     }
778 
779     sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(
780             static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window)));
781     if (cs == nullptr) {
782         // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure
783         // the returned bitmap has a color space.
784         cs = SkColorSpace::MakeSRGB();
785     }
786     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs);
787     return bitmap::createBitmap(env, bitmap.release(),
788             android::bitmap::kBitmapCreateFlag_Premultiplied);
789 }
790 
android_view_ThreadedRenderer_disableVsync(JNIEnv *,jclass)791 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
792     RenderProxy::disableVsync();
793 }
794 
android_view_ThreadedRenderer_setHighContrastText(JNIEnv *,jclass,jboolean enable)795 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
796     Properties::enableHighContrastText = enable;
797 }
798 
android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv *,jclass,jboolean enable)799 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
800     Properties::debuggingEnabled = enable;
801 }
802 
android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv *,jclass,jboolean isolated)803 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
804     Properties::isolatedProcess = isolated;
805 }
806 
android_view_ThreadedRenderer_setContextPriority(JNIEnv *,jclass,jint contextPriority)807 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
808         jint contextPriority) {
809     Properties::contextPriority = contextPriority;
810 }
811 
android_view_ThreadedRenderer_allocateBuffers(JNIEnv * env,jobject clazz,jlong proxyPtr)812 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
813         jlong proxyPtr) {
814     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
815     proxy->allocateBuffers();
816 }
817 
android_view_ThreadedRenderer_setForceDark(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean enable)818 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
819         jlong proxyPtr, jboolean enable) {
820     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
821     proxy->setForceDark(enable);
822 }
823 
android_view_ThreadedRenderer_preload(JNIEnv *,jclass)824 static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
825     RenderProxy::preload();
826 }
827 
android_view_ThreadedRenderer_setRtAnimationsEnabled(JNIEnv * env,jobject clazz,jboolean enabled)828 static void android_view_ThreadedRenderer_setRtAnimationsEnabled(JNIEnv* env, jobject clazz,
829                                                                  jboolean enabled) {
830     RenderProxy::setRtAnimationsEnabled(enabled);
831 }
832 
android_view_ThreadedRenderer_notifyCallbackPending(JNIEnv *,jclass,jlong proxyPtr)833 static void android_view_ThreadedRenderer_notifyCallbackPending(JNIEnv*, jclass, jlong proxyPtr) {
834     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
835     proxy->notifyCallbackPending();
836 }
837 
android_view_ThreadedRenderer_notifyExpensiveFrame(JNIEnv *,jclass,jlong proxyPtr)838 static void android_view_ThreadedRenderer_notifyExpensiveFrame(JNIEnv*, jclass, jlong proxyPtr) {
839     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
840     proxy->notifyExpensiveFrame();
841 }
842 
843 // Plumbs the display density down to DeviceInfo.
android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv *,jclass,jint densityDpi)844 static void android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv*, jclass, jint densityDpi) {
845     // Convert from dpi to density-independent pixels.
846     const float density = densityDpi / 160.0;
847     DeviceInfo::setDensity(density);
848 }
849 
android_view_ThreadedRenderer_initDisplayInfo(JNIEnv * env,jclass,jint physicalWidth,jint physicalHeight,jfloat refreshRate,jint wideColorDataspace,jlong appVsyncOffsetNanos,jlong presentationDeadlineNanos,jboolean supportFp16ForHdr,jboolean supportMixedColorSpaces)850 static void android_view_ThreadedRenderer_initDisplayInfo(
851         JNIEnv* env, jclass, jint physicalWidth, jint physicalHeight, jfloat refreshRate,
852         jint wideColorDataspace, jlong appVsyncOffsetNanos, jlong presentationDeadlineNanos,
853         jboolean supportFp16ForHdr, jboolean supportMixedColorSpaces) {
854     DeviceInfo::setWidth(physicalWidth);
855     DeviceInfo::setHeight(physicalHeight);
856     DeviceInfo::setRefreshRate(refreshRate);
857     DeviceInfo::setWideColorDataspace(static_cast<ADataSpace>(wideColorDataspace));
858     DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
859     DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
860     DeviceInfo::setSupportFp16ForHdr(supportFp16ForHdr);
861     DeviceInfo::setSupportMixedColorSpaces(supportMixedColorSpaces);
862 }
863 
android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv *,jclass,jboolean enabled)864 static void android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv*, jclass, jboolean enabled) {
865     Properties::setDrawingEnabled(enabled);
866 }
867 
android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv *,jclass)868 static jboolean android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv*, jclass) {
869     return Properties::isDrawingEnabled();
870 }
871 
872 // ----------------------------------------------------------------------------
873 // HardwareRendererObserver
874 // ----------------------------------------------------------------------------
875 
android_view_ThreadedRenderer_addObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)876 static void android_view_ThreadedRenderer_addObserver(JNIEnv* env, jclass clazz,
877         jlong proxyPtr, jlong observerPtr) {
878     HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
879     renderthread::RenderProxy* renderProxy =
880             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
881 
882     renderProxy->addFrameMetricsObserver(observer);
883 }
884 
android_view_ThreadedRenderer_removeObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)885 static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass clazz,
886         jlong proxyPtr, jlong observerPtr) {
887     HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
888     renderthread::RenderProxy* renderProxy =
889             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
890 
891     renderProxy->removeFrameMetricsObserver(observer);
892 }
893 
894 // ----------------------------------------------------------------------------
895 // Shaders
896 // ----------------------------------------------------------------------------
897 
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath,jstring skiaDiskCachePath)898 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
899         jstring diskCachePath, jstring skiaDiskCachePath) {
900     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
901     android::egl_set_cache_filename(cacheArray);
902     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
903 
904     const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
905     uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
906     env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
907 }
908 
android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv * env,jobject clazz)909 static jboolean android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv* env, jobject clazz) {
910     // this value is valid only after loadSystemProperties() is called
911     return Properties::enableWebViewOverlays;
912 }
913 
914 // ----------------------------------------------------------------------------
915 // JNI Glue
916 // ----------------------------------------------------------------------------
917 
918 const char* const kClassPathName = "android/graphics/HardwareRenderer";
919 
920 static const JNINativeMethod gMethods[] = {
921         {"nRotateProcessStatsBuffer", "()V",
922          (void*)android_view_ThreadedRenderer_rotateProcessStatsBuffer},
923         {"nSetProcessStatsBuffer", "(I)V",
924          (void*)android_view_ThreadedRenderer_setProcessStatsBuffer},
925         {"nGetRenderThreadTid", "(J)I", (void*)android_view_ThreadedRenderer_getRenderThreadTid},
926         {"nCreateRootRenderNode", "()J", (void*)android_view_ThreadedRenderer_createRootRenderNode},
927         {"nCreateProxy", "(ZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
928         {"nDeleteProxy", "(J)V", (void*)android_view_ThreadedRenderer_deleteProxy},
929         {"nLoadSystemProperties", "(J)Z",
930          (void*)android_view_ThreadedRenderer_loadSystemProperties},
931         {"nSetName", "(JLjava/lang/String;)V", (void*)android_view_ThreadedRenderer_setName},
932         {"nSetSurface", "(JLandroid/view/Surface;Z)V",
933          (void*)android_view_ThreadedRenderer_setSurface},
934         {"nSetSurfaceControl", "(JJ)V", (void*)android_view_ThreadedRenderer_setSurfaceControl},
935         {"nPause", "(J)Z", (void*)android_view_ThreadedRenderer_pause},
936         {"nSetStopped", "(JZ)V", (void*)android_view_ThreadedRenderer_setStopped},
937         {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
938         {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
939         {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
940         {"nSetColorMode", "(JI)F", (void*)android_view_ThreadedRenderer_setColorMode},
941         {"nSetTargetSdrHdrRatio", "(JF)V",
942          (void*)android_view_ThreadedRenderer_setTargetSdrHdrRatio},
943         {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
944         {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx},
945         {"nSetIsLowRam", "(Z)V", (void*)android_view_ThreadedRenderer_setIsLowRam},
946         {"nSetIsSystemOrPersistent", "(Z)V",
947          (void*)android_view_ThreadedRenderer_setIsSystemOrPersistent},
948         {"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
949         {"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
950         {"nRegisterAnimatingRenderNode", "(JJ)V",
951          (void*)android_view_ThreadedRenderer_registerAnimatingRenderNode},
952         {"nRegisterVectorDrawableAnimator", "(JJ)V",
953          (void*)android_view_ThreadedRenderer_registerVectorDrawableAnimator},
954         {"nCreateTextureLayer", "(J)J", (void*)android_view_ThreadedRenderer_createTextureLayer},
955         {"nBuildLayer", "(JJ)V", (void*)android_view_ThreadedRenderer_buildLayer},
956         {"nCopyLayerInto", "(JJJ)Z", (void*)android_view_ThreadedRenderer_copyLayerInto},
957         {"nPushLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_pushLayerUpdate},
958         {"nCancelLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_cancelLayerUpdate},
959         {"nDetachSurfaceTexture", "(JJ)V",
960          (void*)android_view_ThreadedRenderer_detachSurfaceTexture},
961         {"nDestroyHardwareResources", "(J)V",
962          (void*)android_view_ThreadedRenderer_destroyHardwareResources},
963         {"nTrimMemory", "(I)V", (void*)android_view_ThreadedRenderer_trimMemory},
964         {"nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
965          (void*)android_view_ThreadedRenderer_overrideProperty},
966         {"nFence", "(J)V", (void*)android_view_ThreadedRenderer_fence},
967         {"nStopDrawing", "(J)V", (void*)android_view_ThreadedRenderer_stopDrawing},
968         {"nNotifyFramePending", "(J)V", (void*)android_view_ThreadedRenderer_notifyFramePending},
969         {"nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V",
970          (void*)android_view_ThreadedRenderer_dumpProfileInfo},
971         {"nDumpGlobalProfileInfo", "(Ljava/io/FileDescriptor;I)V",
972          (void*)android_view_ThreadedRenderer_dumpGlobalProfileInfo},
973         {"setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V",
974          (void*)android_view_ThreadedRenderer_setupShadersDiskCache},
975         {"nAddRenderNode", "(JJZ)V", (void*)android_view_ThreadedRenderer_addRenderNode},
976         {"nRemoveRenderNode", "(JJ)V", (void*)android_view_ThreadedRenderer_removeRenderNode},
977         {"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode},
978         {"nSetContentDrawBounds", "(JIIII)V",
979          (void*)android_view_ThreadedRenderer_setContentDrawBounds},
980         {"nForceDrawNextFrame", "(J)V", (void*)android_view_ThreadedRenderer_forceDrawNextFrame},
981         {"nSetPictureCaptureCallback",
982          "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V",
983          (void*)android_view_ThreadedRenderer_setPictureCapturedCallbackJNI},
984         {"nSetASurfaceTransactionCallback",
985          "(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V",
986          (void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback},
987         {"nSetPrepareSurfaceControlForWebviewCallback",
988          "(JLandroid/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback;)V",
989          (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
990         {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
991          (void*)android_view_ThreadedRenderer_setFrameCallback},
992         {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
993          (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
994         {"nSetFrameCompleteCallback",
995          "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
996          (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
997         {"nAddObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_addObserver},
998         {"nRemoveObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_removeObserver},
999         {"nCopySurfaceInto",
1000          "(Landroid/view/Surface;IIIILandroid/graphics/HardwareRenderer$CopyRequest;)V",
1001          (void*)android_view_ThreadedRenderer_copySurfaceInto},
1002         {"nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
1003          (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode},
1004         {"disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync},
1005         {"nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText},
1006         {"nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled},
1007         {"nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess},
1008         {"nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority},
1009         {"nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers},
1010         {"nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark},
1011         {"nSetDisplayDensityDpi", "(I)V",
1012          (void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
1013         {"nInitDisplayInfo", "(IIFIJJZZ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
1014         {"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
1015         {"isWebViewOverlaysEnabled", "()Z",
1016          (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
1017         {"nSetDrawingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDrawingEnabled},
1018         {"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled},
1019         {"nSetRtAnimationsEnabled", "(Z)V",
1020          (void*)android_view_ThreadedRenderer_setRtAnimationsEnabled},
1021         {"nNotifyCallbackPending", "(J)V",
1022          (void*)android_view_ThreadedRenderer_notifyCallbackPending},
1023         {"nNotifyExpensiveFrame", "(J)V",
1024          (void*)android_view_ThreadedRenderer_notifyExpensiveFrame},
1025         {"nTrimCaches", "(I)V", (void*)android_view_ThreadedRenderer_trimCaches},
1026 };
1027 
1028 static JavaVM* mJvm = nullptr;
1029 
attachRenderThreadToJvm(const char * name)1030 static void attachRenderThreadToJvm(const char* name) {
1031     LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??");
1032 
1033     JavaVMAttachArgs args;
1034     args.version = JNI_VERSION_1_4;
1035     args.name = name;
1036     args.group = NULL;
1037     JNIEnv* env;
1038     mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args);
1039 }
1040 
register_android_view_ThreadedRenderer(JNIEnv * env)1041 int register_android_view_ThreadedRenderer(JNIEnv* env) {
1042     env->GetJavaVM(&mJvm);
1043     RenderThread::setOnStartHook(&attachRenderThreadToJvm);
1044 
1045     jclass hardwareRenderer = FindClassOrDie(env,
1046             "android/graphics/HardwareRenderer");
1047     gHardwareRenderer.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(hardwareRenderer));
1048     gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
1049             "invokePictureCapturedCallback",
1050             "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
1051 
1052     jclass aSurfaceTransactionCallbackClass =
1053             FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
1054     gASurfaceTransactionCallback.onMergeTransaction =
1055             GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)Z");
1056 
1057     jclass prepareSurfaceControlForWebviewCallbackClass = FindClassOrDie(
1058             env, "android/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback");
1059     gPrepareSurfaceControlForWebviewCallback.prepare =
1060             GetMethodIDOrDie(env, prepareSurfaceControlForWebviewCallbackClass, "prepare", "()V");
1061 
1062     jclass frameCallbackClass = FindClassOrDie(env,
1063             "android/graphics/HardwareRenderer$FrameDrawingCallback");
1064     gFrameDrawingCallback.onFrameDraw =
1065             GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw",
1066                              "(IJ)Landroid/graphics/HardwareRenderer$FrameCommitCallback;");
1067 
1068     jclass frameCommitClass =
1069             FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
1070     gFrameCommitCallback.onFrameCommit =
1071             GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");
1072 
1073     jclass frameCompleteClass = FindClassOrDie(env,
1074             "android/graphics/HardwareRenderer$FrameCompleteCallback");
1075     gFrameCompleteCallback.onFrameComplete =
1076             GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");
1077 
1078     jclass copyRequest = FindClassOrDie(env, "android/graphics/HardwareRenderer$CopyRequest");
1079     gCopyRequest.onCopyFinished = GetMethodIDOrDie(env, copyRequest, "onCopyFinished", "(I)V");
1080     gCopyRequest.getDestinationBitmap =
1081             GetMethodIDOrDie(env, copyRequest, "getDestinationBitmap", "(II)J");
1082 
1083     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
1084     fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
1085     LOG_ALWAYS_FATAL_IF(fromSurface == nullptr,
1086                         "Failed to find required symbol ANativeWindow_fromSurface!");
1087 
1088     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1089 }
1090 
1091 }; // namespace android
1092