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 #define LOG_TAG "ThreadedRenderer"
18 
19 #include <algorithm>
20 
21 #include "jni.h"
22 #include <nativehelper/JNIHelp.h>
23 #include "core_jni_helpers.h"
24 #include <GraphicsJNI.h>
25 #include <ScopedPrimitiveArray.h>
26 
27 #include <EGL/egl.h>
28 #include <EGL/eglext.h>
29 #include <EGL/egl_cache.h>
30 
31 #include <utils/StrongPointer.h>
32 #include <android_runtime/android_view_Surface.h>
33 #include <system/window.h>
34 
35 #include "android_view_GraphicBuffer.h"
36 
37 #include <Animator.h>
38 #include <AnimationContext.h>
39 #include <IContextFactory.h>
40 #include <JankTracker.h>
41 #include <RenderNode.h>
42 #include <renderthread/CanvasContext.h>
43 #include <renderthread/RenderProxy.h>
44 #include <renderthread/RenderTask.h>
45 #include <renderthread/RenderThread.h>
46 #include <Vector.h>
47 
48 namespace android {
49 
50 using namespace android::uirenderer;
51 using namespace android::uirenderer::renderthread;
52 
getenv(JavaVM * vm)53 static JNIEnv* getenv(JavaVM* vm) {
54     JNIEnv* env;
55     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
56         LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
57     }
58     return env;
59 }
60 
61 class OnFinishedEvent {
62 public:
OnFinishedEvent(BaseRenderNodeAnimator * animator,AnimationListener * listener)63     OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
64             : animator(animator), listener(listener) {}
65     sp<BaseRenderNodeAnimator> animator;
66     sp<AnimationListener> listener;
67 };
68 
69 class InvokeAnimationListeners : public MessageHandler {
70 public:
InvokeAnimationListeners(std::vector<OnFinishedEvent> & events)71     InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
72         mOnFinishedEvents.swap(events);
73     }
74 
callOnFinished(OnFinishedEvent & event)75     static void callOnFinished(OnFinishedEvent& event) {
76         event.listener->onAnimationFinished(event.animator.get());
77     }
78 
handleMessage(const Message & message)79     virtual void handleMessage(const Message& message) {
80         std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
81         mOnFinishedEvents.clear();
82     }
83 
84 private:
85     std::vector<OnFinishedEvent> mOnFinishedEvents;
86 };
87 
88 class RenderingException : public MessageHandler {
89 public:
RenderingException(JavaVM * vm,const std::string & message)90     RenderingException(JavaVM* vm, const std::string& message)
91             : mVm(vm)
92             , mMessage(message) {
93     }
94 
handleMessage(const Message &)95     virtual void handleMessage(const Message&) {
96         throwException(mVm, mMessage);
97     }
98 
throwException(JavaVM * vm,const std::string & message)99     static void throwException(JavaVM* vm, const std::string& message) {
100         JNIEnv* env = getenv(vm);
101         jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
102     }
103 
104 private:
105     JavaVM* mVm;
106     std::string mMessage;
107 };
108 
109 class RootRenderNode : public RenderNode, ErrorHandler {
110 public:
RootRenderNode(JNIEnv * env)111     RootRenderNode(JNIEnv* env) : RenderNode() {
112         mLooper = Looper::getForThread();
113         LOG_ALWAYS_FATAL_IF(!mLooper.get(),
114                 "Must create RootRenderNode on a thread with a looper!");
115         env->GetJavaVM(&mVm);
116     }
117 
~RootRenderNode()118     virtual ~RootRenderNode() {}
119 
onError(const std::string & message)120     virtual void onError(const std::string& message) {
121         mLooper->sendMessage(new RenderingException(mVm, message), 0);
122     }
123 
prepareTree(TreeInfo & info)124     virtual void prepareTree(TreeInfo& info) {
125         info.errorHandler = this;
126         RenderNode::prepareTree(info);
127         info.errorHandler = NULL;
128     }
129 
sendMessage(const sp<MessageHandler> & handler)130     void sendMessage(const sp<MessageHandler>& handler) {
131         mLooper->sendMessage(handler, 0);
132     }
133 
attachAnimatingNode(RenderNode * animatingNode)134     void attachAnimatingNode(RenderNode* animatingNode) {
135         mPendingAnimatingRenderNodes.push_back(animatingNode);
136     }
137 
doAttachAnimatingNodes(AnimationContext * context)138     void doAttachAnimatingNodes(AnimationContext* context) {
139         for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
140             RenderNode* node = mPendingAnimatingRenderNodes[i].get();
141             context->addAnimatingRenderNode(*node);
142         }
143         mPendingAnimatingRenderNodes.clear();
144     }
145 
146 private:
147     sp<Looper> mLooper;
148     JavaVM* mVm;
149     std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
150 };
151 
152 class AnimationContextBridge : public AnimationContext {
153 public:
AnimationContextBridge(renderthread::TimeLord & clock,RootRenderNode * rootNode)154     AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
155             : AnimationContext(clock), mRootNode(rootNode) {
156     }
157 
~AnimationContextBridge()158     virtual ~AnimationContextBridge() {}
159 
160     // Marks the start of a frame, which will update the frame time and move all
161     // next frame animations into the current frame
startFrame(TreeInfo::TraversalMode mode)162     virtual void startFrame(TreeInfo::TraversalMode mode) {
163         if (mode == TreeInfo::MODE_FULL) {
164             mRootNode->doAttachAnimatingNodes(this);
165         }
166         AnimationContext::startFrame(mode);
167     }
168 
169     // Runs any animations still left in mCurrentFrameAnimations
runRemainingAnimations(TreeInfo & info)170     virtual void runRemainingAnimations(TreeInfo& info) {
171         AnimationContext::runRemainingAnimations(info);
172         postOnFinishedEvents();
173     }
174 
callOnFinished(BaseRenderNodeAnimator * animator,AnimationListener * listener)175     virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
176         OnFinishedEvent event(animator, listener);
177         mOnFinishedEvents.push_back(event);
178     }
179 
destroy()180     virtual void destroy() {
181         AnimationContext::destroy();
182         postOnFinishedEvents();
183     }
184 
185 private:
186     sp<RootRenderNode> mRootNode;
187     std::vector<OnFinishedEvent> mOnFinishedEvents;
188 
postOnFinishedEvents()189     void postOnFinishedEvents() {
190         if (mOnFinishedEvents.size()) {
191             sp<InvokeAnimationListeners> message
192                     = new InvokeAnimationListeners(mOnFinishedEvents);
193             mRootNode->sendMessage(message);
194         }
195     }
196 };
197 
198 class ContextFactoryImpl : public IContextFactory {
199 public:
ContextFactoryImpl(RootRenderNode * rootNode)200     ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
201 
createAnimationContext(renderthread::TimeLord & clock)202     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
203         return new AnimationContextBridge(clock, mRootNode);
204     }
205 
206 private:
207     RootRenderNode* mRootNode;
208 };
209 
android_view_ThreadedRenderer_setAtlas(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject graphicBuffer,jlongArray atlasMapArray)210 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
211         jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
212     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
213     jsize len = env->GetArrayLength(atlasMapArray);
214     if (len <= 0) {
215         ALOGW("Failed to initialize atlas, invalid map length: %d", len);
216         return;
217     }
218     int64_t* map = new int64_t[len];
219     env->GetLongArrayRegion(atlasMapArray, 0, len, map);
220 
221     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
222     proxy->setTextureAtlas(buffer, map, len);
223 }
224 
android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv * env,jobject clazz,jlong proxyPtr,jint fd)225 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
226         jlong proxyPtr, jint fd) {
227     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
228     proxy->setProcessStatsBuffer(fd);
229 }
230 
android_view_ThreadedRenderer_createRootRenderNode(JNIEnv * env,jobject clazz)231 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
232     RootRenderNode* node = new RootRenderNode(env);
233     node->incStrong(0);
234     node->setName("RootRenderNode");
235     return reinterpret_cast<jlong>(node);
236 }
237 
android_view_ThreadedRenderer_createProxy(JNIEnv * env,jobject clazz,jboolean translucent,jlong rootRenderNodePtr)238 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
239         jboolean translucent, jlong rootRenderNodePtr) {
240     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
241     ContextFactoryImpl factory(rootRenderNode);
242     return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
243 }
244 
android_view_ThreadedRenderer_deleteProxy(JNIEnv * env,jobject clazz,jlong proxyPtr)245 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
246         jlong proxyPtr) {
247     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248     delete proxy;
249 }
250 
android_view_ThreadedRenderer_loadSystemProperties(JNIEnv * env,jobject clazz,jlong proxyPtr)251 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
252         jlong proxyPtr) {
253     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
254     return proxy->loadSystemProperties();
255 }
256 
android_view_ThreadedRenderer_setName(JNIEnv * env,jobject clazz,jlong proxyPtr,jstring jname)257 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
258         jlong proxyPtr, jstring jname) {
259     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
260     const char* name = env->GetStringUTFChars(jname, NULL);
261     proxy->setName(name);
262     env->ReleaseStringUTFChars(jname, name);
263 }
264 
android_view_ThreadedRenderer_initialize(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)265 static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
266         jlong proxyPtr, jobject jsurface) {
267     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
268     sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
269     return proxy->initialize(window);
270 }
271 
android_view_ThreadedRenderer_updateSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)272 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
273         jlong proxyPtr, jobject jsurface) {
274     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
275     sp<ANativeWindow> window;
276     if (jsurface) {
277         window = android_view_Surface_getNativeWindow(env, jsurface);
278     }
279     proxy->updateSurface(window);
280 }
281 
android_view_ThreadedRenderer_pauseSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)282 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
283         jlong proxyPtr, jobject jsurface) {
284     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
285     sp<ANativeWindow> window;
286     if (jsurface) {
287         window = android_view_Surface_getNativeWindow(env, jsurface);
288     }
289     return proxy->pauseSurface(window);
290 }
291 
android_view_ThreadedRenderer_setup(JNIEnv * env,jobject clazz,jlong proxyPtr,jint width,jint height,jfloat lightRadius,jint ambientShadowAlpha,jint spotShadowAlpha)292 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
293         jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
294     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
295     proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha);
296 }
297 
android_view_ThreadedRenderer_setLightCenter(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat lightX,jfloat lightY,jfloat lightZ)298 static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
299         jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
300     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
301     proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
302 }
303 
android_view_ThreadedRenderer_setOpaque(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean opaque)304 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
305         jlong proxyPtr, jboolean opaque) {
306     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
307     proxy->setOpaque(opaque);
308 }
309 
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlongArray frameInfo,jint frameInfoSize)310 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
311         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
312     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
313             "Mismatched size expectations, given %d expected %d",
314             frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
315     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
316     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
317     return proxy->syncAndDrawFrame();
318 }
319 
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr)320 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
321         jlong proxyPtr) {
322     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
323     proxy->destroy();
324 }
325 
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)326 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
327         jlong rootNodePtr, jlong animatingNodePtr) {
328     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
329     RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
330     rootRenderNode->attachAnimatingNode(animatingNode);
331 }
332 
android_view_ThreadedRenderer_invokeFunctor(JNIEnv * env,jobject clazz,jlong functorPtr,jboolean waitForCompletion)333 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
334         jlong functorPtr, jboolean waitForCompletion) {
335     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
336     RenderProxy::invokeFunctor(functor, waitForCompletion);
337 }
338 
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)339 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
340         jlong proxyPtr) {
341     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
342     DeferredLayerUpdater* layer = proxy->createTextureLayer();
343     return reinterpret_cast<jlong>(layer);
344 }
345 
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)346 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
347         jlong proxyPtr, jlong nodePtr) {
348     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
349     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
350     proxy->buildLayer(node);
351 }
352 
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jobject jbitmap)353 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
354         jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
355     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
356     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
357     SkBitmap bitmap;
358     GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
359     return proxy->copyLayerInto(layer, bitmap);
360 }
361 
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)362 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
363         jlong proxyPtr, jlong layerPtr) {
364     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
365     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
366     proxy->pushLayerUpdate(layer);
367 }
368 
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)369 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
370         jlong proxyPtr, jlong layerPtr) {
371     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
372     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
373     proxy->cancelLayerUpdate(layer);
374 }
375 
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)376 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
377         jlong proxyPtr, jlong layerPtr) {
378     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
379     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
380     proxy->detachSurfaceTexture(layer);
381 }
382 
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)383 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
384         jlong proxyPtr) {
385     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
386     proxy->destroyHardwareResources();
387 }
388 
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)389 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
390         jint level) {
391     RenderProxy::trimMemory(level);
392 }
393 
android_view_ThreadedRenderer_overrideProperty(JNIEnv * env,jobject clazz,jstring name,jstring value)394 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
395         jstring name, jstring value) {
396     const char* nameCharArray = env->GetStringUTFChars(name, NULL);
397     const char* valueCharArray = env->GetStringUTFChars(value, NULL);
398     RenderProxy::overrideProperty(nameCharArray, valueCharArray);
399     env->ReleaseStringUTFChars(name, nameCharArray);
400     env->ReleaseStringUTFChars(name, valueCharArray);
401 }
402 
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)403 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
404         jlong proxyPtr) {
405     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
406     proxy->fence();
407 }
408 
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)409 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
410         jlong proxyPtr) {
411     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
412     proxy->stopDrawing();
413 }
414 
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)415 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
416         jlong proxyPtr) {
417     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
418     proxy->notifyFramePending();
419 }
420 
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor,jint dumpFlags)421 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
422         jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
423     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
424     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
425     proxy->dumpProfileInfo(fd, dumpFlags);
426 }
427 
android_view_ThreadedRenderer_dumpProfileData(JNIEnv * env,jobject clazz,jbyteArray jdata,jobject javaFileDescriptor)428 static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
429         jbyteArray jdata, jobject javaFileDescriptor) {
430     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
431     ScopedByteArrayRO buffer(env, jdata);
432     if (buffer.get()) {
433         JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
434     }
435 }
436 
437 
438 // ----------------------------------------------------------------------------
439 // Shaders
440 // ----------------------------------------------------------------------------
441 
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath)442 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
443         jstring diskCachePath) {
444 
445     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
446     egl_cache_t::get()->setCacheFilename(cacheArray);
447     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
448 }
449 
450 // ----------------------------------------------------------------------------
451 // JNI Glue
452 // ----------------------------------------------------------------------------
453 
454 const char* const kClassPathName = "android/view/ThreadedRenderer";
455 
456 static JNINativeMethod gMethods[] = {
457     { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
458     { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
459     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
460     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
461     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
462     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
463     { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
464     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
465     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
466     { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
467     { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
468     { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
469     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
470     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
471     { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
472     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
473     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
474     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
475     { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
476     { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
477     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
478     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
479     { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
480     { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
481     { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
482     { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
483     { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
484     { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
485     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
486     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
487     { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
488     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
489                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
490 };
491 
register_android_view_ThreadedRenderer(JNIEnv * env)492 int register_android_view_ThreadedRenderer(JNIEnv* env) {
493     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
494 }
495 
496 }; // namespace android
497