android_view_ThreadedRenderer.cpp revision d5c7dd6da810a6b89151b337bea79fd817e6b72a
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#include <atomic>
21
22#include "jni.h"
23#include <nativehelper/JNIHelp.h>
24#include "core_jni_helpers.h"
25#include <GraphicsJNI.h>
26#include <ScopedPrimitiveArray.h>
27
28#include <EGL/egl.h>
29#include <EGL/eglext.h>
30#include <EGL/egl_cache.h>
31
32#include <utils/Looper.h>
33#include <utils/RefBase.h>
34#include <utils/StrongPointer.h>
35#include <utils/Timers.h>
36#include <android_runtime/android_view_Surface.h>
37#include <system/window.h>
38
39#include "android_os_MessageQueue.h"
40
41#include <Animator.h>
42#include <AnimationContext.h>
43#include <FrameInfo.h>
44#include <FrameMetricsObserver.h>
45#include <IContextFactory.h>
46#include <PropertyValuesAnimatorSet.h>
47#include <RenderNode.h>
48#include <renderthread/CanvasContext.h>
49#include <renderthread/RenderProxy.h>
50#include <renderthread/RenderTask.h>
51#include <renderthread/RenderThread.h>
52
53namespace android {
54
55using namespace android::uirenderer;
56using namespace android::uirenderer::renderthread;
57
58struct {
59    jfieldID frameMetrics;
60    jfieldID timingDataBuffer;
61    jfieldID messageQueue;
62    jmethodID callback;
63} gFrameMetricsObserverClassInfo;
64
65static JNIEnv* getenv(JavaVM* vm) {
66    JNIEnv* env;
67    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
68        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
69    }
70    return env;
71}
72
73class OnFinishedEvent {
74public:
75    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
76            : animator(animator), listener(listener) {}
77    sp<BaseRenderNodeAnimator> animator;
78    sp<AnimationListener> listener;
79};
80
81class InvokeAnimationListeners : public MessageHandler {
82public:
83    explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
84        mOnFinishedEvents.swap(events);
85    }
86
87    static void callOnFinished(OnFinishedEvent& event) {
88        event.listener->onAnimationFinished(event.animator.get());
89    }
90
91    virtual void handleMessage(const Message& message) {
92        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
93        mOnFinishedEvents.clear();
94    }
95
96private:
97    std::vector<OnFinishedEvent> mOnFinishedEvents;
98};
99
100class FinishAndInvokeListener : public MessageHandler {
101public:
102    explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim)
103            : mAnimator(anim) {
104        mListener = anim->getOneShotListener();
105        mRequestId = anim->getRequestId();
106    }
107
108    virtual void handleMessage(const Message& message) {
109        if (mAnimator->getRequestId() == mRequestId) {
110            // Request Id has not changed, meaning there's no animation lifecyle change since the
111            // message is posted, so go ahead and call finish to make sure the PlayState is properly
112            // updated. This is needed because before the next frame comes in from UI thread to
113            // trigger an animation update, there could be reverse/cancel etc. So we need to update
114            // the playstate in time to ensure all the subsequent events get chained properly.
115            mAnimator->end();
116        }
117        mListener->onAnimationFinished(nullptr);
118    }
119private:
120    sp<PropertyValuesAnimatorSet> mAnimator;
121    sp<AnimationListener> mListener;
122    uint32_t mRequestId;
123};
124
125class RenderingException : public MessageHandler {
126public:
127    RenderingException(JavaVM* vm, const std::string& message)
128            : mVm(vm)
129            , mMessage(message) {
130    }
131
132    virtual void handleMessage(const Message&) {
133        throwException(mVm, mMessage);
134    }
135
136    static void throwException(JavaVM* vm, const std::string& message) {
137        JNIEnv* env = getenv(vm);
138        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
139    }
140
141private:
142    JavaVM* mVm;
143    std::string mMessage;
144};
145
146class RootRenderNode : public RenderNode, ErrorHandler {
147public:
148    explicit RootRenderNode(JNIEnv* env) : RenderNode() {
149        mLooper = Looper::getForThread();
150        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
151                "Must create RootRenderNode on a thread with a looper!");
152        env->GetJavaVM(&mVm);
153    }
154
155    virtual ~RootRenderNode() {}
156
157    virtual void onError(const std::string& message) override {
158        mLooper->sendMessage(new RenderingException(mVm, message), 0);
159    }
160
161    virtual void prepareTree(TreeInfo& info) override {
162        info.errorHandler = this;
163
164        for (auto& anim : mRunningVDAnimators) {
165            // Assume that the property change in VD from the animators will not be consumed. Mark
166            // otherwise if the VDs are found in the display list tree. For VDs that are not in
167            // the display list tree, we stop providing animation pulses by 1) removing them from
168            // the animation list, 2) post a delayed message to end them at end time so their
169            // listeners can receive the corresponding callbacks.
170            anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
171            // Mark the VD dirty so it will damage itself during prepareTree.
172            anim->getVectorDrawable()->markDirty();
173        }
174        if (info.mode == TreeInfo::MODE_FULL) {
175            for (auto &anim : mPausedVDAnimators) {
176                anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
177                anim->getVectorDrawable()->markDirty();
178            }
179        }
180        // TODO: This is hacky
181        info.updateWindowPositions = true;
182        RenderNode::prepareTree(info);
183        info.updateWindowPositions = false;
184        info.errorHandler = nullptr;
185    }
186
187    void sendMessage(const sp<MessageHandler>& handler) {
188        mLooper->sendMessage(handler, 0);
189    }
190
191    void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) {
192        mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0);
193    }
194
195    void attachAnimatingNode(RenderNode* animatingNode) {
196        mPendingAnimatingRenderNodes.push_back(animatingNode);
197    }
198
199    void attachPendingVectorDrawableAnimators() {
200        mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(),
201                mPendingVectorDrawableAnimators.end());
202        mPendingVectorDrawableAnimators.clear();
203    }
204
205    void detachAnimators() {
206        // Remove animators from the list and post a delayed message in future to end the animator
207        for (auto& anim : mRunningVDAnimators) {
208            detachVectorDrawableAnimator(anim.get());
209        }
210        mRunningVDAnimators.clear();
211        mPausedVDAnimators.clear();
212    }
213
214    // Move all the animators to the paused list, and send a delayed message to notify the finished
215    // listener.
216    void pauseAnimators() {
217        mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end());
218        for (auto& anim : mRunningVDAnimators) {
219            detachVectorDrawableAnimator(anim.get());
220        }
221        mRunningVDAnimators.clear();
222    }
223
224    void doAttachAnimatingNodes(AnimationContext* context) {
225        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
226            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
227            context->addAnimatingRenderNode(*node);
228        }
229        mPendingAnimatingRenderNodes.clear();
230    }
231
232    // Run VectorDrawable animators after prepareTree.
233    void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) {
234        // Push staging.
235        if (info.mode == TreeInfo::MODE_FULL) {
236            pushStagingVectorDrawableAnimators(context);
237        }
238
239        // Run the animators in the running list.
240        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
241            if ((*it)->animate(*context)) {
242                it = mRunningVDAnimators.erase(it);
243            } else {
244                it++;
245            }
246        }
247
248        // Run the animators in paused list during full sync.
249        if (info.mode == TreeInfo::MODE_FULL) {
250            // During full sync we also need to pulse paused animators, in case their targets
251            // have been added back to the display list. All the animators that passed the
252            // scheduled finish time will be removed from the paused list.
253            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
254                if ((*it)->animate(*context)) {
255                    // Animator has finished, remove from the list.
256                    it = mPausedVDAnimators.erase(it);
257                } else {
258                    it++;
259                }
260            }
261        }
262
263        // Move the animators with a target not in DisplayList to paused list.
264        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
265            if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
266                // Vector Drawable is not in the display list, we should remove this animator from
267                // the list, put it in the paused list, and post a delayed message to end the
268                // animator.
269                detachVectorDrawableAnimator(it->get());
270                mPausedVDAnimators.insert(*it);
271                it = mRunningVDAnimators.erase(it);
272            } else {
273                it++;
274            }
275        }
276
277        // Move the animators with a target in DisplayList from paused list to running list, and
278        // trim paused list.
279        if (info.mode == TreeInfo::MODE_FULL) {
280            // Check whether any paused animator's target is back in Display List. If so, put the
281            // animator back in the running list.
282            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
283                if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
284                    mRunningVDAnimators.insert(*it);
285                    it = mPausedVDAnimators.erase(it);
286                } else {
287                    it++;
288                }
289            }
290            // Trim paused VD animators at full sync, so that when Java loses reference to an
291            // animator, we know we won't be requested to animate it any more, then we remove such
292            // animators from the paused list so they can be properly freed. We also remove the
293            // animators from paused list when the time elapsed since start has exceeded duration.
294            trimPausedVDAnimators(context);
295        }
296
297        info.out.hasAnimations |= !mRunningVDAnimators.empty();
298    }
299
300    void trimPausedVDAnimators(AnimationContext* context) {
301        // Trim paused vector drawable animator list.
302        for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
303            // Remove paused VD animator if no one else is referencing it. Note that animators that
304            // have passed scheduled finish time are removed from list when they are being pulsed
305            // before prepare tree.
306            // TODO: this is a bit hacky, need to figure out a better way to track when the paused
307            // animators should be freed.
308            if ((*it)->getStrongCount() == 1) {
309                it = mPausedVDAnimators.erase(it);
310            } else {
311                it++;
312            }
313        }
314    }
315
316    void pushStagingVectorDrawableAnimators(AnimationContext* context) {
317        for (auto& anim : mRunningVDAnimators) {
318            anim->pushStaging(*context);
319        }
320    }
321
322    void destroy() {
323        for (auto& renderNode : mPendingAnimatingRenderNodes) {
324            renderNode->animators().endAllStagingAnimators();
325        }
326        mPendingAnimatingRenderNodes.clear();
327        mPendingVectorDrawableAnimators.clear();
328    }
329
330    void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
331        mPendingVectorDrawableAnimators.insert(anim);
332    }
333
334private:
335    sp<Looper> mLooper;
336    JavaVM* mVm;
337    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
338    std::set< sp<PropertyValuesAnimatorSet> > mPendingVectorDrawableAnimators;
339    std::set< sp<PropertyValuesAnimatorSet> > mRunningVDAnimators;
340    // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but
341    // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when
342    // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators
343    // need to be re-activated once their VD target is added back into DisplayList. Since that could
344    // only happen when we do a full sync, we need to make sure to pulse these paused animators at
345    // full sync. If any animator's VD target is found in DisplayList during a full sync, we move
346    // the animator back to the running list.
347    std::set< sp<PropertyValuesAnimatorSet> > mPausedVDAnimators;
348    void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
349        if (anim->isInfinite() || !anim->isRunning()) {
350            // Do not need to post anything if the animation is infinite (i.e. no meaningful
351            // end listener action), or if the animation has already ended.
352            return;
353        }
354        nsecs_t remainingTimeInMs = anim->getRemainingPlayTime();
355        // Post a delayed onFinished event that is scheduled to be handled when the animator ends.
356        if (anim->getOneShotListener()) {
357            // VectorDrawable's oneshot listener is updated when there are user triggered animation
358            // lifecycle changes, such as start(), end(), etc. By using checking and clearing
359            // one shot listener, we ensure the same end listener event gets posted only once.
360            // Therefore no duplicates. Another benefit of using one shot listener is that no
361            // removal is necessary: the end time of animation will not change unless triggered by
362            // user events, in which case the already posted listener's id will become stale, and
363            // the onFinished callback will then be ignored.
364            sp<FinishAndInvokeListener> message
365                    = new FinishAndInvokeListener(anim);
366            sendMessageDelayed(message, remainingTimeInMs);
367            anim->clearOneShotListener();
368        }
369    }
370};
371
372class AnimationContextBridge : public AnimationContext {
373public:
374    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
375            : AnimationContext(clock), mRootNode(rootNode) {
376    }
377
378    virtual ~AnimationContextBridge() {}
379
380    // Marks the start of a frame, which will update the frame time and move all
381    // next frame animations into the current frame
382    virtual void startFrame(TreeInfo::TraversalMode mode) {
383        if (mode == TreeInfo::MODE_FULL) {
384            mRootNode->doAttachAnimatingNodes(this);
385            mRootNode->attachPendingVectorDrawableAnimators();
386        }
387        AnimationContext::startFrame(mode);
388    }
389
390    // Runs any animations still left in mCurrentFrameAnimations
391    virtual void runRemainingAnimations(TreeInfo& info) {
392        AnimationContext::runRemainingAnimations(info);
393        mRootNode->runVectorDrawableAnimators(this, info);
394        postOnFinishedEvents();
395    }
396
397    virtual void pauseAnimators() override {
398        mRootNode->pauseAnimators();
399    }
400
401    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
402        OnFinishedEvent event(animator, listener);
403        mOnFinishedEvents.push_back(event);
404    }
405
406    virtual void destroy() {
407        AnimationContext::destroy();
408        mRootNode->detachAnimators();
409        postOnFinishedEvents();
410    }
411
412private:
413    sp<RootRenderNode> mRootNode;
414    std::vector<OnFinishedEvent> mOnFinishedEvents;
415
416    void postOnFinishedEvents() {
417        if (mOnFinishedEvents.size()) {
418            sp<InvokeAnimationListeners> message
419                    = new InvokeAnimationListeners(mOnFinishedEvents);
420            mRootNode->sendMessage(message);
421        }
422    }
423};
424
425class ContextFactoryImpl : public IContextFactory {
426public:
427    explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
428
429    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
430        return new AnimationContextBridge(clock, mRootNode);
431    }
432
433private:
434    RootRenderNode* mRootNode;
435};
436
437class ObserverProxy;
438
439class NotifyHandler : public MessageHandler {
440public:
441    NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {}
442
443    virtual void handleMessage(const Message& message);
444
445private:
446    JavaVM* const mVm;
447    ObserverProxy* const mObserver;
448};
449
450static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
451    jobject frameMetrics = env->GetObjectField(
452            observer, gFrameMetricsObserverClassInfo.frameMetrics);
453    LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
454    jobject buffer = env->GetObjectField(
455            frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
456    LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
457    return reinterpret_cast<jlongArray>(buffer);
458}
459
460/*
461 * Implements JNI layer for hwui frame metrics reporting.
462 */
463class ObserverProxy : public FrameMetricsObserver {
464public:
465    ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
466        JNIEnv* env = getenv(mVm);
467
468        mObserverWeak = env->NewWeakGlobalRef(observer);
469        LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
470                "unable to create frame stats observer reference");
471
472        jlongArray buffer = get_metrics_buffer(env, observer);
473        jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
474        LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
475                "Mismatched Java/Native FrameMetrics data format.");
476
477        jobject messageQueueLocal = env->GetObjectField(
478                observer, gFrameMetricsObserverClassInfo.messageQueue);
479        mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
480        LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
481
482        mMessageHandler = new NotifyHandler(mVm, this);
483        LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
484                "OOM: unable to allocate NotifyHandler");
485    }
486
487    ~ObserverProxy() {
488        JNIEnv* env = getenv(mVm);
489        env->DeleteWeakGlobalRef(mObserverWeak);
490    }
491
492    jweak getObserverReference() {
493        return mObserverWeak;
494    }
495
496    bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
497        FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
498
499        if (elem.hasData.load()) {
500            env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
501            *dropCount = elem.dropCount;
502            mNextInQueue = (mNextInQueue + 1) % kRingSize;
503            elem.hasData = false;
504            return true;
505        }
506
507        return false;
508    }
509
510    virtual void notify(const int64_t* stats) {
511        FrameMetricsNotification& elem = mRingBuffer[mNextFree];
512
513        if (!elem.hasData.load()) {
514            memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
515
516            elem.dropCount = mDroppedReports;
517            mDroppedReports = 0;
518
519            incStrong(nullptr);
520            mNextFree = (mNextFree + 1) % kRingSize;
521            elem.hasData = true;
522
523            mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
524        } else {
525            mDroppedReports++;
526        }
527    }
528
529private:
530    static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
531    static constexpr int kRingSize = 3;
532
533    class FrameMetricsNotification {
534    public:
535        FrameMetricsNotification() : hasData(false) {}
536
537        std::atomic_bool hasData;
538        int64_t buffer[kBufferSize];
539        int dropCount = 0;
540    };
541
542    JavaVM* const mVm;
543    jweak mObserverWeak;
544
545    sp<MessageQueue> mMessageQueue;
546    sp<NotifyHandler> mMessageHandler;
547    Message mMessage;
548
549    int mNextFree = 0;
550    int mNextInQueue = 0;
551    FrameMetricsNotification mRingBuffer[kRingSize];
552
553    int mDroppedReports = 0;
554};
555
556void NotifyHandler::handleMessage(const Message& message) {
557    JNIEnv* env = getenv(mVm);
558
559    jobject target = env->NewLocalRef(mObserver->getObserverReference());
560
561    if (target != nullptr) {
562        jlongArray javaBuffer = get_metrics_buffer(env, target);
563        int dropCount = 0;
564        while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
565            env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
566        }
567        env->DeleteLocalRef(target);
568    }
569
570    mObserver->decStrong(nullptr);
571}
572
573static jboolean android_view_ThreadedRenderer_supportsOpenGL(JNIEnv* env, jobject clazz) {
574    char prop[PROPERTY_VALUE_MAX];
575    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
576        // not in the emulator
577        return JNI_TRUE;
578    }
579    // In the emulator this property will be set > 0 when OpenGL ES 2.0 is
580    // enabled, 0 otherwise. On old emulator versions it will be undefined.
581    property_get("qemu.gles", prop, "0");
582    return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE;
583}
584
585static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
586    RenderProxy::rotateProcessStatsBuffer();
587}
588
589static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
590        jint fd) {
591    RenderProxy::setProcessStatsBuffer(fd);
592}
593
594static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
595        jlong proxyPtr) {
596    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
597    return proxy->getRenderThreadTid();
598}
599
600static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
601    RootRenderNode* node = new RootRenderNode(env);
602    node->incStrong(0);
603    node->setName("RootRenderNode");
604    return reinterpret_cast<jlong>(node);
605}
606
607static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
608        jboolean translucent, jlong rootRenderNodePtr) {
609    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
610    ContextFactoryImpl factory(rootRenderNode);
611    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
612}
613
614static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
615        jlong proxyPtr) {
616    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
617    delete proxy;
618}
619
620static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
621        jlong proxyPtr) {
622    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
623    return proxy->loadSystemProperties();
624}
625
626static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
627        jlong proxyPtr, jstring jname) {
628    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
629    const char* name = env->GetStringUTFChars(jname, NULL);
630    proxy->setName(name);
631    env->ReleaseStringUTFChars(jname, name);
632}
633
634static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
635        jlong proxyPtr, jobject jsurface) {
636    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
637    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
638    proxy->initialize(surface);
639}
640
641static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
642        jlong proxyPtr, jobject jsurface) {
643    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
644    sp<Surface> surface;
645    if (jsurface) {
646        surface = android_view_Surface_getSurface(env, jsurface);
647    }
648    proxy->updateSurface(surface);
649}
650
651static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
652        jlong proxyPtr, jobject jsurface) {
653    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
654    sp<Surface> surface;
655    if (jsurface) {
656        surface = android_view_Surface_getSurface(env, jsurface);
657    }
658    return proxy->pauseSurface(surface);
659}
660
661static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
662        jlong proxyPtr, jboolean stopped) {
663    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
664    proxy->setStopped(stopped);
665}
666
667static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
668        jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
669    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
670    proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
671}
672
673static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
674        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
675    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
676    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
677}
678
679static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
680        jlong proxyPtr, jboolean opaque) {
681    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
682    proxy->setOpaque(opaque);
683}
684
685static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
686        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
687    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
688            "Mismatched size expectations, given %d expected %d",
689            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
690    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
691    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
692    return proxy->syncAndDrawFrame();
693}
694
695static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
696        jlong proxyPtr, jlong rootNodePtr) {
697    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
698    rootRenderNode->destroy();
699    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
700    proxy->destroy();
701}
702
703static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
704        jlong rootNodePtr, jlong animatingNodePtr) {
705    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
706    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
707    rootRenderNode->attachAnimatingNode(animatingNode);
708}
709
710static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
711        jlong rootNodePtr, jlong animatorPtr) {
712    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
713    PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
714    rootRenderNode->addVectorDrawableAnimator(animator);
715}
716
717static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
718        jlong functorPtr, jboolean waitForCompletion) {
719    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
720    RenderProxy::invokeFunctor(functor, waitForCompletion);
721}
722
723static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
724        jlong proxyPtr) {
725    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
726    DeferredLayerUpdater* layer = proxy->createTextureLayer();
727    return reinterpret_cast<jlong>(layer);
728}
729
730static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
731        jlong proxyPtr, jlong nodePtr) {
732    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
733    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
734    proxy->buildLayer(node);
735}
736
737static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
738        jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
739    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
740    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
741    SkBitmap bitmap;
742    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
743    return proxy->copyLayerInto(layer, bitmap);
744}
745
746static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
747        jlong proxyPtr, jlong layerPtr) {
748    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
749    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
750    proxy->pushLayerUpdate(layer);
751}
752
753static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
754        jlong proxyPtr, jlong layerPtr) {
755    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
756    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
757    proxy->cancelLayerUpdate(layer);
758}
759
760static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
761        jlong proxyPtr, jlong layerPtr) {
762    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
763    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
764    proxy->detachSurfaceTexture(layer);
765}
766
767static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
768        jlong proxyPtr) {
769    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
770    proxy->destroyHardwareResources();
771}
772
773static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
774        jint level) {
775    RenderProxy::trimMemory(level);
776}
777
778static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
779        jstring name, jstring value) {
780    const char* nameCharArray = env->GetStringUTFChars(name, NULL);
781    const char* valueCharArray = env->GetStringUTFChars(value, NULL);
782    RenderProxy::overrideProperty(nameCharArray, valueCharArray);
783    env->ReleaseStringUTFChars(name, nameCharArray);
784    env->ReleaseStringUTFChars(name, valueCharArray);
785}
786
787static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
788        jlong proxyPtr) {
789    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
790    proxy->fence();
791}
792
793static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
794        jlong proxyPtr) {
795    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
796    proxy->stopDrawing();
797}
798
799static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
800        jlong proxyPtr) {
801    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
802    proxy->notifyFramePending();
803}
804
805static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
806        jlong proxyPtr) {
807    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
808    proxy->serializeDisplayListTree();
809}
810
811static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
812        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
813    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
814    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
815    proxy->dumpProfileInfo(fd, dumpFlags);
816}
817
818static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
819        jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
820    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
821    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
822    proxy->addRenderNode(renderNode, placeFront);
823}
824
825static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
826        jlong proxyPtr, jlong renderNodePtr) {
827    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
828    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
829    proxy->removeRenderNode(renderNode);
830}
831
832static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
833        jlong proxyPtr, jlong renderNodePtr) {
834    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
835    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
836    proxy->drawRenderNode(renderNode);
837}
838
839static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
840        jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
841    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
842    proxy->setContentDrawBounds(left, top, right, bottom);
843}
844
845static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
846        jobject clazz, jobject jsurface, jint left, jint top,
847        jint right, jint bottom, jobject jbitmap) {
848    SkBitmap bitmap;
849    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
850    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
851    return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap);
852}
853
854// ----------------------------------------------------------------------------
855// FrameMetricsObserver
856// ----------------------------------------------------------------------------
857
858static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
859        jclass clazz, jlong proxyPtr, jobject fso) {
860    JavaVM* vm = nullptr;
861    if (env->GetJavaVM(&vm) != JNI_OK) {
862        LOG_ALWAYS_FATAL("Unable to get Java VM");
863        return 0;
864    }
865
866    renderthread::RenderProxy* renderProxy =
867            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
868
869    FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
870    renderProxy->addFrameMetricsObserver(observer);
871    return reinterpret_cast<jlong>(observer);
872}
873
874static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
875        jlong proxyPtr, jlong observerPtr) {
876    FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
877    renderthread::RenderProxy* renderProxy =
878            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
879
880    renderProxy->removeFrameMetricsObserver(observer);
881}
882
883// ----------------------------------------------------------------------------
884// Shaders
885// ----------------------------------------------------------------------------
886
887static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
888        jstring diskCachePath) {
889    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
890    egl_cache_t::get()->setCacheFilename(cacheArray);
891    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
892}
893
894// ----------------------------------------------------------------------------
895// JNI Glue
896// ----------------------------------------------------------------------------
897
898const char* const kClassPathName = "android/view/ThreadedRenderer";
899
900static const JNINativeMethod gMethods[] = {
901    { "nSupportsOpenGL", "()Z", (void*) android_view_ThreadedRenderer_supportsOpenGL },
902    { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
903    { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
904    { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid },
905    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
906    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
907    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
908    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
909    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
910    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
911    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
912    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
913    { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
914    { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
915    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
916    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
917    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
918    { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
919    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
920    { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator },
921    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
922    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
923    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
924    { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
925    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
926    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
927    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
928    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
929    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
930    { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
931    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
932    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
933    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
934    { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
935    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
936    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
937                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
938    { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
939    { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
940    { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
941    { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
942    { "nAddFrameMetricsObserver",
943            "(JLandroid/view/FrameMetricsObserver;)J",
944            (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
945    { "nRemoveFrameMetricsObserver",
946            "(JJ)V",
947            (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
948    { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I",
949                (void*)android_view_ThreadedRenderer_copySurfaceInto },
950};
951
952int register_android_view_ThreadedRenderer(JNIEnv* env) {
953    jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
954    gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
955            env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
956    gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
957            env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
958    gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
959            env, observerClass, "notifyDataAvailable", "(I)V");
960
961    jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
962    gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
963            env, metricsClass, "mTimingData", "[J");
964
965    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
966}
967
968}; // namespace android
969