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