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