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#define ATRACE_TAG ATRACE_TAG_VIEW
19
20#include <algorithm>
21#include <atomic>
22#include <inttypes.h>
23
24#include "jni.h"
25#include <nativehelper/JNIHelp.h>
26#include "core_jni_helpers.h"
27#include <GraphicsJNI.h>
28#include <nativehelper/ScopedPrimitiveArray.h>
29
30#include <gui/BufferItemConsumer.h>
31#include <gui/BufferQueue.h>
32#include <gui/Surface.h>
33
34#include <EGL/egl.h>
35#include <EGL/eglext.h>
36#include <private/EGL/cache.h>
37
38#include <utils/Looper.h>
39#include <utils/RefBase.h>
40#include <utils/StrongPointer.h>
41#include <utils/Timers.h>
42#include <utils/TraceUtils.h>
43#include <android_runtime/android_view_Surface.h>
44#include <system/window.h>
45
46#include "android_os_MessageQueue.h"
47
48#include <Animator.h>
49#include <AnimationContext.h>
50#include <FrameInfo.h>
51#include <FrameMetricsObserver.h>
52#include <IContextFactory.h>
53#include <Properties.h>
54#include <PropertyValuesAnimatorSet.h>
55#include <RenderNode.h>
56#include <renderthread/CanvasContext.h>
57#include <renderthread/RenderProxy.h>
58#include <renderthread/RenderTask.h>
59#include <renderthread/RenderThread.h>
60#include <pipeline/skia/ShaderCache.h>
61
62namespace android {
63
64using namespace android::uirenderer;
65using namespace android::uirenderer::renderthread;
66
67struct {
68    jfieldID frameMetrics;
69    jfieldID timingDataBuffer;
70    jfieldID messageQueue;
71    jmethodID callback;
72} gFrameMetricsObserverClassInfo;
73
74struct {
75    jmethodID onFrameDraw;
76} gFrameDrawingCallback;
77
78struct {
79    jmethodID onFrameComplete;
80} gFrameCompleteCallback;
81
82static JNIEnv* getenv(JavaVM* vm) {
83    JNIEnv* env;
84    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
85        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
86    }
87    return env;
88}
89
90class OnFinishedEvent {
91public:
92    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
93            : animator(animator), listener(listener) {}
94    sp<BaseRenderNodeAnimator> animator;
95    sp<AnimationListener> listener;
96};
97
98class InvokeAnimationListeners : public MessageHandler {
99public:
100    explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
101        mOnFinishedEvents.swap(events);
102    }
103
104    static void callOnFinished(OnFinishedEvent& event) {
105        event.listener->onAnimationFinished(event.animator.get());
106    }
107
108    virtual void handleMessage(const Message& message) {
109        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
110        mOnFinishedEvents.clear();
111    }
112
113private:
114    std::vector<OnFinishedEvent> mOnFinishedEvents;
115};
116
117class FinishAndInvokeListener : public MessageHandler {
118public:
119    explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim)
120            : mAnimator(anim) {
121        mListener = anim->getOneShotListener();
122        mRequestId = anim->getRequestId();
123    }
124
125    virtual void handleMessage(const Message& message) {
126        if (mAnimator->getRequestId() == mRequestId) {
127            // Request Id has not changed, meaning there's no animation lifecyle change since the
128            // message is posted, so go ahead and call finish to make sure the PlayState is properly
129            // updated. This is needed because before the next frame comes in from UI thread to
130            // trigger an animation update, there could be reverse/cancel etc. So we need to update
131            // the playstate in time to ensure all the subsequent events get chained properly.
132            mAnimator->end();
133        }
134        mListener->onAnimationFinished(nullptr);
135    }
136private:
137    sp<PropertyValuesAnimatorSet> mAnimator;
138    sp<AnimationListener> mListener;
139    uint32_t mRequestId;
140};
141
142class RenderingException : public MessageHandler {
143public:
144    RenderingException(JavaVM* vm, const std::string& message)
145            : mVm(vm)
146            , mMessage(message) {
147    }
148
149    virtual void handleMessage(const Message&) {
150        throwException(mVm, mMessage);
151    }
152
153    static void throwException(JavaVM* vm, const std::string& message) {
154        JNIEnv* env = getenv(vm);
155        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
156    }
157
158private:
159    JavaVM* mVm;
160    std::string mMessage;
161};
162
163class FrameCompleteWrapper : public MessageHandler {
164public:
165    FrameCompleteWrapper(JNIEnv* env, jobject jobject) {
166        mLooper = Looper::getForThread();
167        LOG_ALWAYS_FATAL_IF(!mLooper.get(), "Must create runnable on a Looper thread!");
168        env->GetJavaVM(&mVm);
169        mObject = env->NewGlobalRef(jobject);
170        LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
171    }
172
173    virtual ~FrameCompleteWrapper() {
174        releaseObject();
175    }
176
177    void postFrameComplete(int64_t frameNr) {
178        if (mObject) {
179            mFrameNr = frameNr;
180            mLooper->sendMessage(this, 0);
181        }
182    }
183
184    virtual void handleMessage(const Message&) {
185        if (mObject) {
186            ATRACE_FORMAT("frameComplete %" PRId64, mFrameNr);
187            getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, mFrameNr);
188            releaseObject();
189        }
190    }
191
192private:
193    JavaVM* mVm;
194    jobject mObject;
195    sp<Looper> mLooper;
196    int64_t mFrameNr = -1;
197
198    void releaseObject() {
199        if (mObject) {
200            getenv(mVm)->DeleteGlobalRef(mObject);
201            mObject = nullptr;
202        }
203    }
204};
205
206class RootRenderNode : public RenderNode, ErrorHandler {
207public:
208    explicit RootRenderNode(JNIEnv* env) : RenderNode() {
209        mLooper = Looper::getForThread();
210        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
211                "Must create RootRenderNode on a thread with a looper!");
212        env->GetJavaVM(&mVm);
213    }
214
215    virtual ~RootRenderNode() {}
216
217    virtual void onError(const std::string& message) override {
218        mLooper->sendMessage(new RenderingException(mVm, message), 0);
219    }
220
221    virtual void prepareTree(TreeInfo& info) override {
222        info.errorHandler = this;
223
224        for (auto& anim : mRunningVDAnimators) {
225            // Assume that the property change in VD from the animators will not be consumed. Mark
226            // otherwise if the VDs are found in the display list tree. For VDs that are not in
227            // the display list tree, we stop providing animation pulses by 1) removing them from
228            // the animation list, 2) post a delayed message to end them at end time so their
229            // listeners can receive the corresponding callbacks.
230            anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
231            // Mark the VD dirty so it will damage itself during prepareTree.
232            anim->getVectorDrawable()->markDirty();
233        }
234        if (info.mode == TreeInfo::MODE_FULL) {
235            for (auto &anim : mPausedVDAnimators) {
236                anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
237                anim->getVectorDrawable()->markDirty();
238            }
239        }
240        // TODO: This is hacky
241        info.updateWindowPositions = true;
242        RenderNode::prepareTree(info);
243        info.updateWindowPositions = false;
244        info.errorHandler = nullptr;
245    }
246
247    void sendMessage(const sp<MessageHandler>& handler) {
248        mLooper->sendMessage(handler, 0);
249    }
250
251    void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) {
252        mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0);
253    }
254
255    void attachAnimatingNode(RenderNode* animatingNode) {
256        mPendingAnimatingRenderNodes.push_back(animatingNode);
257    }
258
259    void attachPendingVectorDrawableAnimators() {
260        mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(),
261                mPendingVectorDrawableAnimators.end());
262        mPendingVectorDrawableAnimators.clear();
263    }
264
265    void detachAnimators() {
266        // Remove animators from the list and post a delayed message in future to end the animator
267        // For infinite animators, remove the listener so we no longer hold a global ref to the AVD
268        // java object, and therefore the AVD objects in both native and Java can be properly
269        // released.
270        for (auto& anim : mRunningVDAnimators) {
271            detachVectorDrawableAnimator(anim.get());
272            anim->clearOneShotListener();
273        }
274        for (auto& anim : mPausedVDAnimators) {
275            anim->clearOneShotListener();
276        }
277        mRunningVDAnimators.clear();
278        mPausedVDAnimators.clear();
279    }
280
281    // Move all the animators to the paused list, and send a delayed message to notify the finished
282    // listener.
283    void pauseAnimators() {
284        mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end());
285        for (auto& anim : mRunningVDAnimators) {
286            detachVectorDrawableAnimator(anim.get());
287        }
288        mRunningVDAnimators.clear();
289    }
290
291    void doAttachAnimatingNodes(AnimationContext* context) {
292        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
293            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
294            context->addAnimatingRenderNode(*node);
295        }
296        mPendingAnimatingRenderNodes.clear();
297    }
298
299    // Run VectorDrawable animators after prepareTree.
300    void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) {
301        // Push staging.
302        if (info.mode == TreeInfo::MODE_FULL) {
303            pushStagingVectorDrawableAnimators(context);
304        }
305
306        // Run the animators in the running list.
307        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
308            if ((*it)->animate(*context)) {
309                it = mRunningVDAnimators.erase(it);
310            } else {
311                it++;
312            }
313        }
314
315        // Run the animators in paused list during full sync.
316        if (info.mode == TreeInfo::MODE_FULL) {
317            // During full sync we also need to pulse paused animators, in case their targets
318            // have been added back to the display list. All the animators that passed the
319            // scheduled finish time will be removed from the paused list.
320            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
321                if ((*it)->animate(*context)) {
322                    // Animator has finished, remove from the list.
323                    it = mPausedVDAnimators.erase(it);
324                } else {
325                    it++;
326                }
327            }
328        }
329
330        // Move the animators with a target not in DisplayList to paused list.
331        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
332            if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
333                // Vector Drawable is not in the display list, we should remove this animator from
334                // the list, put it in the paused list, and post a delayed message to end the
335                // animator.
336                detachVectorDrawableAnimator(it->get());
337                mPausedVDAnimators.insert(*it);
338                it = mRunningVDAnimators.erase(it);
339            } else {
340                it++;
341            }
342        }
343
344        // Move the animators with a target in DisplayList from paused list to running list, and
345        // trim paused list.
346        if (info.mode == TreeInfo::MODE_FULL) {
347            // Check whether any paused animator's target is back in Display List. If so, put the
348            // animator back in the running list.
349            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
350                if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
351                    mRunningVDAnimators.insert(*it);
352                    it = mPausedVDAnimators.erase(it);
353                } else {
354                    it++;
355                }
356            }
357            // Trim paused VD animators at full sync, so that when Java loses reference to an
358            // animator, we know we won't be requested to animate it any more, then we remove such
359            // animators from the paused list so they can be properly freed. We also remove the
360            // animators from paused list when the time elapsed since start has exceeded duration.
361            trimPausedVDAnimators(context);
362        }
363
364        info.out.hasAnimations |= !mRunningVDAnimators.empty();
365    }
366
367    void trimPausedVDAnimators(AnimationContext* context) {
368        // Trim paused vector drawable animator list.
369        for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
370            // Remove paused VD animator if no one else is referencing it. Note that animators that
371            // have passed scheduled finish time are removed from list when they are being pulsed
372            // before prepare tree.
373            // TODO: this is a bit hacky, need to figure out a better way to track when the paused
374            // animators should be freed.
375            if ((*it)->getStrongCount() == 1) {
376                it = mPausedVDAnimators.erase(it);
377            } else {
378                it++;
379            }
380        }
381    }
382
383    void pushStagingVectorDrawableAnimators(AnimationContext* context) {
384        for (auto& anim : mRunningVDAnimators) {
385            anim->pushStaging(*context);
386        }
387    }
388
389    void destroy() {
390        for (auto& renderNode : mPendingAnimatingRenderNodes) {
391            renderNode->animators().endAllStagingAnimators();
392        }
393        mPendingAnimatingRenderNodes.clear();
394        mPendingVectorDrawableAnimators.clear();
395    }
396
397    void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
398        mPendingVectorDrawableAnimators.insert(anim);
399    }
400
401private:
402    sp<Looper> mLooper;
403    JavaVM* mVm;
404    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
405    std::set< sp<PropertyValuesAnimatorSet> > mPendingVectorDrawableAnimators;
406    std::set< sp<PropertyValuesAnimatorSet> > mRunningVDAnimators;
407    // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but
408    // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when
409    // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators
410    // need to be re-activated once their VD target is added back into DisplayList. Since that could
411    // only happen when we do a full sync, we need to make sure to pulse these paused animators at
412    // full sync. If any animator's VD target is found in DisplayList during a full sync, we move
413    // the animator back to the running list.
414    std::set< sp<PropertyValuesAnimatorSet> > mPausedVDAnimators;
415    void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
416        if (anim->isInfinite() || !anim->isRunning()) {
417            // Do not need to post anything if the animation is infinite (i.e. no meaningful
418            // end listener action), or if the animation has already ended.
419            return;
420        }
421        nsecs_t remainingTimeInMs = anim->getRemainingPlayTime();
422        // Post a delayed onFinished event that is scheduled to be handled when the animator ends.
423        if (anim->getOneShotListener()) {
424            // VectorDrawable's oneshot listener is updated when there are user triggered animation
425            // lifecycle changes, such as start(), end(), etc. By using checking and clearing
426            // one shot listener, we ensure the same end listener event gets posted only once.
427            // Therefore no duplicates. Another benefit of using one shot listener is that no
428            // removal is necessary: the end time of animation will not change unless triggered by
429            // user events, in which case the already posted listener's id will become stale, and
430            // the onFinished callback will then be ignored.
431            sp<FinishAndInvokeListener> message
432                    = new FinishAndInvokeListener(anim);
433            sendMessageDelayed(message, remainingTimeInMs);
434            anim->clearOneShotListener();
435        }
436    }
437};
438
439class AnimationContextBridge : public AnimationContext {
440public:
441    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
442            : AnimationContext(clock), mRootNode(rootNode) {
443    }
444
445    virtual ~AnimationContextBridge() {}
446
447    // Marks the start of a frame, which will update the frame time and move all
448    // next frame animations into the current frame
449    virtual void startFrame(TreeInfo::TraversalMode mode) {
450        if (mode == TreeInfo::MODE_FULL) {
451            mRootNode->doAttachAnimatingNodes(this);
452            mRootNode->attachPendingVectorDrawableAnimators();
453        }
454        AnimationContext::startFrame(mode);
455    }
456
457    // Runs any animations still left in mCurrentFrameAnimations
458    virtual void runRemainingAnimations(TreeInfo& info) {
459        AnimationContext::runRemainingAnimations(info);
460        mRootNode->runVectorDrawableAnimators(this, info);
461        postOnFinishedEvents();
462    }
463
464    virtual void pauseAnimators() override {
465        mRootNode->pauseAnimators();
466    }
467
468    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
469        OnFinishedEvent event(animator, listener);
470        mOnFinishedEvents.push_back(event);
471    }
472
473    virtual void destroy() {
474        AnimationContext::destroy();
475        mRootNode->detachAnimators();
476        postOnFinishedEvents();
477    }
478
479private:
480    sp<RootRenderNode> mRootNode;
481    std::vector<OnFinishedEvent> mOnFinishedEvents;
482
483    void postOnFinishedEvents() {
484        if (mOnFinishedEvents.size()) {
485            sp<InvokeAnimationListeners> message
486                    = new InvokeAnimationListeners(mOnFinishedEvents);
487            mRootNode->sendMessage(message);
488        }
489    }
490};
491
492class ContextFactoryImpl : public IContextFactory {
493public:
494    explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
495
496    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
497        return new AnimationContextBridge(clock, mRootNode);
498    }
499
500private:
501    RootRenderNode* mRootNode;
502};
503
504class ObserverProxy;
505
506class NotifyHandler : public MessageHandler {
507public:
508    NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {}
509
510    virtual void handleMessage(const Message& message);
511
512private:
513    JavaVM* const mVm;
514    ObserverProxy* const mObserver;
515};
516
517static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
518    jobject frameMetrics = env->GetObjectField(
519            observer, gFrameMetricsObserverClassInfo.frameMetrics);
520    LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
521    jobject buffer = env->GetObjectField(
522            frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
523    LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
524    return reinterpret_cast<jlongArray>(buffer);
525}
526
527/*
528 * Implements JNI layer for hwui frame metrics reporting.
529 */
530class ObserverProxy : public FrameMetricsObserver {
531public:
532    ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
533        JNIEnv* env = getenv(mVm);
534
535        mObserverWeak = env->NewWeakGlobalRef(observer);
536        LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
537                "unable to create frame stats observer reference");
538
539        jlongArray buffer = get_metrics_buffer(env, observer);
540        jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
541        LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
542                "Mismatched Java/Native FrameMetrics data format.");
543
544        jobject messageQueueLocal = env->GetObjectField(
545                observer, gFrameMetricsObserverClassInfo.messageQueue);
546        mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
547        LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
548
549        mMessageHandler = new NotifyHandler(mVm, this);
550        LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
551                "OOM: unable to allocate NotifyHandler");
552    }
553
554    ~ObserverProxy() {
555        JNIEnv* env = getenv(mVm);
556        env->DeleteWeakGlobalRef(mObserverWeak);
557    }
558
559    jweak getObserverReference() {
560        return mObserverWeak;
561    }
562
563    bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
564        FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
565
566        if (elem.hasData.load()) {
567            env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
568            *dropCount = elem.dropCount;
569            mNextInQueue = (mNextInQueue + 1) % kRingSize;
570            elem.hasData = false;
571            return true;
572        }
573
574        return false;
575    }
576
577    virtual void notify(const int64_t* stats) {
578        FrameMetricsNotification& elem = mRingBuffer[mNextFree];
579
580        if (!elem.hasData.load()) {
581            memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
582
583            elem.dropCount = mDroppedReports;
584            mDroppedReports = 0;
585
586            incStrong(nullptr);
587            mNextFree = (mNextFree + 1) % kRingSize;
588            elem.hasData = true;
589
590            mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
591        } else {
592            mDroppedReports++;
593        }
594    }
595
596private:
597    static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
598    static constexpr int kRingSize = 3;
599
600    class FrameMetricsNotification {
601    public:
602        FrameMetricsNotification() : hasData(false) {}
603
604        std::atomic_bool hasData;
605        int64_t buffer[kBufferSize];
606        int dropCount = 0;
607    };
608
609    JavaVM* const mVm;
610    jweak mObserverWeak;
611
612    sp<MessageQueue> mMessageQueue;
613    sp<NotifyHandler> mMessageHandler;
614    Message mMessage;
615
616    int mNextFree = 0;
617    int mNextInQueue = 0;
618    FrameMetricsNotification mRingBuffer[kRingSize];
619
620    int mDroppedReports = 0;
621};
622
623void NotifyHandler::handleMessage(const Message& message) {
624    JNIEnv* env = getenv(mVm);
625
626    jobject target = env->NewLocalRef(mObserver->getObserverReference());
627
628    if (target != nullptr) {
629        jlongArray javaBuffer = get_metrics_buffer(env, target);
630        int dropCount = 0;
631        while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
632            env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
633        }
634        env->DeleteLocalRef(target);
635    }
636
637    mObserver->decStrong(nullptr);
638}
639
640static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
641    RenderProxy::rotateProcessStatsBuffer();
642}
643
644static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
645        jint fd) {
646    RenderProxy::setProcessStatsBuffer(fd);
647}
648
649static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
650        jlong proxyPtr) {
651    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
652    return proxy->getRenderThreadTid();
653}
654
655static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
656    RootRenderNode* node = new RootRenderNode(env);
657    node->incStrong(0);
658    node->setName("RootRenderNode");
659    return reinterpret_cast<jlong>(node);
660}
661
662static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
663        jboolean translucent, jlong rootRenderNodePtr) {
664    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
665    ContextFactoryImpl factory(rootRenderNode);
666    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
667}
668
669static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
670        jlong proxyPtr) {
671    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
672    delete proxy;
673}
674
675static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
676        jlong proxyPtr) {
677    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
678    return proxy->loadSystemProperties();
679}
680
681static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
682        jlong proxyPtr, jstring jname) {
683    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
684    const char* name = env->GetStringUTFChars(jname, NULL);
685    proxy->setName(name);
686    env->ReleaseStringUTFChars(jname, name);
687}
688
689static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
690        jlong proxyPtr, jobject jsurface) {
691    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
692    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
693    proxy->initialize(surface);
694}
695
696static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
697        jlong proxyPtr, jobject jsurface) {
698    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
699    sp<Surface> surface;
700    if (jsurface) {
701        surface = android_view_Surface_getSurface(env, jsurface);
702    }
703    proxy->updateSurface(surface);
704}
705
706static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
707        jlong proxyPtr, jobject jsurface) {
708    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
709    sp<Surface> surface;
710    if (jsurface) {
711        surface = android_view_Surface_getSurface(env, jsurface);
712    }
713    return proxy->pauseSurface(surface);
714}
715
716static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
717        jlong proxyPtr, jboolean stopped) {
718    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
719    proxy->setStopped(stopped);
720}
721
722static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
723        jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
724    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
725    proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
726}
727
728static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
729        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
730    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
731    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
732}
733
734static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
735        jlong proxyPtr, jboolean opaque) {
736    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
737    proxy->setOpaque(opaque);
738}
739
740static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz,
741        jlong proxyPtr, jboolean wideGamut) {
742    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
743    proxy->setWideGamut(wideGamut);
744}
745
746static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
747        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
748    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
749            "Mismatched size expectations, given %d expected %d",
750            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
751    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
752    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
753    return proxy->syncAndDrawFrame();
754}
755
756static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
757        jlong proxyPtr, jlong rootNodePtr) {
758    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
759    rootRenderNode->destroy();
760    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
761    proxy->destroy();
762}
763
764static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
765        jlong rootNodePtr, jlong animatingNodePtr) {
766    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
767    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
768    rootRenderNode->attachAnimatingNode(animatingNode);
769}
770
771static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
772        jlong rootNodePtr, jlong animatorPtr) {
773    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
774    PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
775    rootRenderNode->addVectorDrawableAnimator(animator);
776}
777
778static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
779        jlong functorPtr, jboolean waitForCompletion) {
780    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
781    RenderProxy::invokeFunctor(functor, waitForCompletion);
782}
783
784static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
785        jlong proxyPtr) {
786    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
787    DeferredLayerUpdater* layer = proxy->createTextureLayer();
788    return reinterpret_cast<jlong>(layer);
789}
790
791static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
792        jlong proxyPtr, jlong nodePtr) {
793    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
794    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
795    proxy->buildLayer(node);
796}
797
798static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
799        jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
800    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
801    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
802    SkBitmap bitmap;
803    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
804    return proxy->copyLayerInto(layer, bitmap);
805}
806
807static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
808        jlong proxyPtr, jlong layerPtr) {
809    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
810    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
811    proxy->pushLayerUpdate(layer);
812}
813
814static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
815        jlong proxyPtr, jlong layerPtr) {
816    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
817    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
818    proxy->cancelLayerUpdate(layer);
819}
820
821static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
822        jlong proxyPtr, jlong layerPtr) {
823    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
824    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
825    proxy->detachSurfaceTexture(layer);
826}
827
828static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
829        jlong proxyPtr) {
830    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
831    proxy->destroyHardwareResources();
832}
833
834static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
835        jint level) {
836    RenderProxy::trimMemory(level);
837}
838
839static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
840        jstring name, jstring value) {
841    const char* nameCharArray = env->GetStringUTFChars(name, NULL);
842    const char* valueCharArray = env->GetStringUTFChars(value, NULL);
843    RenderProxy::overrideProperty(nameCharArray, valueCharArray);
844    env->ReleaseStringUTFChars(name, nameCharArray);
845    env->ReleaseStringUTFChars(name, valueCharArray);
846}
847
848static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
849        jlong proxyPtr) {
850    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
851    proxy->fence();
852}
853
854static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
855        jlong proxyPtr) {
856    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
857    proxy->stopDrawing();
858}
859
860static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
861        jlong proxyPtr) {
862    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
863    proxy->notifyFramePending();
864}
865
866static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
867        jlong proxyPtr) {
868    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
869    proxy->serializeDisplayListTree();
870}
871
872static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
873        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
874    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
875    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
876    proxy->dumpProfileInfo(fd, dumpFlags);
877}
878
879static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
880        jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
881    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
882    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
883    proxy->addRenderNode(renderNode, placeFront);
884}
885
886static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
887        jlong proxyPtr, jlong renderNodePtr) {
888    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
889    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
890    proxy->removeRenderNode(renderNode);
891}
892
893static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
894        jlong proxyPtr, jlong renderNodePtr) {
895    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
896    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
897    proxy->drawRenderNode(renderNode);
898}
899
900static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
901        jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
902    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
903    proxy->setContentDrawBounds(left, top, right, bottom);
904}
905
906class JGlobalRefHolder {
907public:
908    JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
909
910    virtual ~JGlobalRefHolder() {
911        getenv(mVm)->DeleteGlobalRef(mObject);
912        mObject = nullptr;
913    }
914
915    jobject object() { return mObject; }
916    JavaVM* vm() { return mVm; }
917
918private:
919    JGlobalRefHolder(const JGlobalRefHolder&) = delete;
920    void operator=(const JGlobalRefHolder&) = delete;
921
922    JavaVM* mVm;
923    jobject mObject;
924};
925
926static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
927        jobject clazz, jlong proxyPtr, jobject frameCallback) {
928    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
929    if (!frameCallback) {
930        proxy->setFrameCallback(nullptr);
931    } else {
932        JavaVM* vm = nullptr;
933        LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
934        auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
935                env->NewGlobalRef(frameCallback));
936        proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) {
937            JNIEnv* env = getenv(globalCallbackRef->vm());
938            env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
939                    static_cast<jlong>(frameNr));
940        });
941    }
942}
943
944static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
945        jobject clazz, jlong proxyPtr, jobject callback) {
946    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
947    if (!callback) {
948        proxy->setFrameCompleteCallback(nullptr);
949    } else {
950        sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
951        proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
952            wrapper->postFrameComplete(frameNr);
953        });
954    }
955}
956
957static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
958        jobject clazz, jobject jsurface, jint left, jint top,
959        jint right, jint bottom, jobject jbitmap) {
960    SkBitmap bitmap;
961    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
962    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
963    return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap);
964}
965
966class ContextFactory : public IContextFactory {
967public:
968    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
969        return new AnimationContext(clock);
970    }
971};
972
973static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
974        jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
975    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
976    if (jwidth <= 0 || jheight <= 0) {
977        ALOGW("Invalid width %d or height %d", jwidth, jheight);
978        return nullptr;
979    }
980
981    uint32_t width = jwidth;
982    uint32_t height = jheight;
983
984    // Create a Surface wired up to a BufferItemConsumer
985    sp<IGraphicBufferProducer> producer;
986    sp<IGraphicBufferConsumer> rawConsumer;
987    BufferQueue::createBufferQueue(&producer, &rawConsumer);
988    // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2
989    rawConsumer->setMaxBufferCount(2);
990    sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer,
991            GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
992    consumer->setDefaultBufferSize(width, height);
993    sp<Surface> surface = new Surface(producer);
994
995    // Render into the surface
996    {
997        ContextFactory factory;
998        RenderProxy proxy{true, renderNode, &factory};
999        proxy.loadSystemProperties();
1000        proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
1001        proxy.initialize(surface);
1002        // Shadows can't be used via this interface, so just set the light source
1003        // to all 0s.
1004        proxy.setup(0, 0, 0);
1005        proxy.setLightCenter((Vector3){0, 0, 0});
1006        nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
1007        UiFrameInfoBuilder(proxy.frameInfo())
1008                .setVsync(vsync, vsync)
1009                .addFlag(FrameInfoFlags::SurfaceCanvas);
1010        proxy.syncAndDrawFrame();
1011    }
1012
1013    // Yank out the GraphicBuffer
1014    BufferItem bufferItem;
1015    status_t err;
1016    if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) {
1017        ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err));
1018        return nullptr;
1019    }
1020    sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer;
1021    // We don't really care if this fails or not since we're just going to destroy this anyway
1022    consumer->releaseBuffer(bufferItem);
1023    if (!buffer.get()) {
1024        ALOGW("GraphicBuffer is null?");
1025        return nullptr;
1026    }
1027    if (buffer->getWidth() != width || buffer->getHeight() != height) {
1028        ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d",
1029                buffer->getWidth(), buffer->getHeight(), width, height);
1030        // Continue I guess?
1031    }
1032    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
1033    return bitmap::createBitmap(env, bitmap.release(),
1034            android::bitmap::kBitmapCreateFlag_Premultiplied);
1035}
1036
1037static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
1038    RenderProxy::disableVsync();
1039}
1040
1041static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
1042    Properties::enableHighContrastText = enable;
1043}
1044
1045static void android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv*, jclass,
1046        jboolean enable) {
1047    Properties::enableRTAnimations = enable;
1048}
1049
1050static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
1051    Properties::debuggingEnabled = enable;
1052}
1053
1054static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
1055    Properties::isolatedProcess = isolated;
1056}
1057
1058static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
1059        jint contextPriority) {
1060    Properties::contextPriority = contextPriority;
1061}
1062
1063// ----------------------------------------------------------------------------
1064// FrameMetricsObserver
1065// ----------------------------------------------------------------------------
1066
1067static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
1068        jclass clazz, jlong proxyPtr, jobject fso) {
1069    JavaVM* vm = nullptr;
1070    if (env->GetJavaVM(&vm) != JNI_OK) {
1071        LOG_ALWAYS_FATAL("Unable to get Java VM");
1072        return 0;
1073    }
1074
1075    renderthread::RenderProxy* renderProxy =
1076            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
1077
1078    FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
1079    renderProxy->addFrameMetricsObserver(observer);
1080    return reinterpret_cast<jlong>(observer);
1081}
1082
1083static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
1084        jlong proxyPtr, jlong observerPtr) {
1085    FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
1086    renderthread::RenderProxy* renderProxy =
1087            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
1088
1089    renderProxy->removeFrameMetricsObserver(observer);
1090}
1091
1092// ----------------------------------------------------------------------------
1093// Shaders
1094// ----------------------------------------------------------------------------
1095
1096static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
1097        jstring diskCachePath, jstring skiaDiskCachePath) {
1098    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
1099    android::egl_set_cache_filename(cacheArray);
1100    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
1101
1102    const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
1103    uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
1104    env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
1105}
1106
1107// ----------------------------------------------------------------------------
1108// JNI Glue
1109// ----------------------------------------------------------------------------
1110
1111const char* const kClassPathName = "android/view/ThreadedRenderer";
1112
1113static const JNINativeMethod gMethods[] = {
1114    { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
1115    { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
1116    { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid },
1117    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
1118    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
1119    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
1120    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
1121    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
1122    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
1123    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
1124    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
1125    { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
1126    { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
1127    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
1128    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
1129    { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
1130    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
1131    { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
1132    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
1133    { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator },
1134    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
1135    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
1136    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
1137    { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
1138    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
1139    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
1140    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
1141    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
1142    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
1143    { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
1144    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
1145    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
1146    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
1147    { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
1148    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
1149    { "setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V",
1150                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
1151    { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
1152    { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
1153    { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
1154    { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
1155    { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
1156            (void*)android_view_ThreadedRenderer_setFrameCallback},
1157    { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
1158            (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
1159    { "nAddFrameMetricsObserver",
1160            "(JLandroid/view/FrameMetricsObserver;)J",
1161            (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
1162    { "nRemoveFrameMetricsObserver",
1163            "(JJ)V",
1164            (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
1165    { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I",
1166                (void*)android_view_ThreadedRenderer_copySurfaceInto },
1167    { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
1168            (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode },
1169    { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync },
1170    { "nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText },
1171    { "nHackySetRTAnimationsEnabled", "(Z)V",
1172            (void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled },
1173    { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
1174    { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
1175    { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
1176};
1177
1178static JavaVM* mJvm = nullptr;
1179
1180static void attachRenderThreadToJvm() {
1181    LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??");
1182
1183    JavaVMAttachArgs args;
1184    args.version = JNI_VERSION_1_4;
1185    args.name = (char*) "RenderThread";
1186    args.group = NULL;
1187    JNIEnv* env;
1188    mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args);
1189}
1190
1191int register_android_view_ThreadedRenderer(JNIEnv* env) {
1192    env->GetJavaVM(&mJvm);
1193    RenderThread::setOnStartHook(&attachRenderThreadToJvm);
1194    jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
1195    gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
1196            env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
1197    gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
1198            env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
1199    gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
1200            env, observerClass, "notifyDataAvailable", "(I)V");
1201
1202    jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
1203    gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
1204            env, metricsClass, "mTimingData", "[J");
1205
1206    jclass frameCallbackClass = FindClassOrDie(env,
1207            "android/view/ThreadedRenderer$FrameDrawingCallback");
1208    gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
1209            "onFrameDraw", "(J)V");
1210
1211    jclass frameCompleteClass = FindClassOrDie(env,
1212            "android/view/ThreadedRenderer$FrameCompleteCallback");
1213    gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
1214            "onFrameComplete", "(J)V");
1215
1216    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1217}
1218
1219}; // namespace android
1220