1cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck/*
2cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Copyright (C) 2010 The Android Open Source Project
3cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
4cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
5cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * you may not use this file except in compliance with the License.
6cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * You may obtain a copy of the License at
7cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
8cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
9cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
10cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Unless required by applicable law or agreed to in writing, software
11cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
12cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * See the License for the specific language governing permissions and
14cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * limitations under the License.
15cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck */
16cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
1723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define LOG_TAG "ThreadedRenderer"
18cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
19e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <algorithm>
2011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales#include <atomic>
21e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
22cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include "jni.h"
23cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <nativehelper/JNIHelp.h>
24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
253731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck#include <GraphicsJNI.h>
26edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <ScopedPrimitiveArray.h>
27cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
2884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/egl.h>
2984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/eglext.h>
3084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/egl_cache.h>
3184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
3206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales#include <utils/Looper.h>
3306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales#include <utils/RefBase.h>
344f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <utils/StrongPointer.h>
354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <android_runtime/android_view_Surface.h>
364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <system/window.h>
374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck#include "android_view_GraphicBuffer.h"
3906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales#include "android_os_MessageQueue.h"
4066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
4152244fff29042926e21fa897ef5ab11148e35299John Reck#include <Animator.h>
42119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include <AnimationContext.h>
4306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales#include <FrameInfo.h>
44910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales#include <FrameMetricsObserver.h>
45119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include <IContextFactory.h>
46edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <JankTracker.h>
47e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <RenderNode.h>
4866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck#include <renderthread/CanvasContext.h>
494f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <renderthread/RenderProxy.h>
50cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <renderthread/RenderTask.h>
51cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <renderthread/RenderThread.h>
52cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
53cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Recknamespace android {
54cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
554f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckusing namespace android::uirenderer;
564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckusing namespace android::uirenderer::renderthread;
57cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
5806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesstruct {
59910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jfieldID frameMetrics;
60910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jfieldID timingDataBuffer;
6106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    jfieldID messageQueue;
62910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jmethodID callback;
63910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales} gFrameMetricsObserverClassInfo;
6406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
65c25e506f7fc08790c0532f927f31310a2ca778b7John Reckstatic JNIEnv* getenv(JavaVM* vm) {
66c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    JNIEnv* env;
67c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
68c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
69c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    }
70c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    return env;
71c25e506f7fc08790c0532f927f31310a2ca778b7John Reck}
72c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
7351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck// TODO: Clean this up, it's a bit odd to need to call over to
7451f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck// rendernode's jni layer. Probably means RootRenderNode should be pulled
7551f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck// into HWUI with appropriate callbacks for the various JNI hooks so
7651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck// that RenderNode's JNI layer can handle its own thing
7751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reckvoid onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
7851f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck
7951f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reckclass ScopedRemovedRenderNodeObserver : public TreeObserver {
8051f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reckpublic:
8151f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
8251f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ~ScopedRemovedRenderNodeObserver() {
8351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck        for (auto& node : mMaybeRemovedNodes) {
8451f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck            if (node->hasParents()) continue;
8551f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck            onRenderNodeRemoved(mEnv, node.get());
8651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck        }
8751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    }
8851f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck
8951f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    virtual void onMaybeRemovedFromTree(RenderNode* node) override {
9051f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck        mMaybeRemovedNodes.insert(sp<RenderNode>(node));
9151f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    }
9251f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck
9351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reckprivate:
9451f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    JNIEnv* mEnv;
9551f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    std::set< sp<RenderNode> > mMaybeRemovedNodes;
9651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck};
9751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck
9852244fff29042926e21fa897ef5ab11148e35299John Reckclass OnFinishedEvent {
9952244fff29042926e21fa897ef5ab11148e35299John Reckpublic:
100ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
10152244fff29042926e21fa897ef5ab11148e35299John Reck            : animator(animator), listener(listener) {}
102ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    sp<BaseRenderNodeAnimator> animator;
10352244fff29042926e21fa897ef5ab11148e35299John Reck    sp<AnimationListener> listener;
10452244fff29042926e21fa897ef5ab11148e35299John Reck};
10552244fff29042926e21fa897ef5ab11148e35299John Reck
106e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckclass InvokeAnimationListeners : public MessageHandler {
107e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckpublic:
10852244fff29042926e21fa897ef5ab11148e35299John Reck    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
10952244fff29042926e21fa897ef5ab11148e35299John Reck        mOnFinishedEvents.swap(events);
110e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
111e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
11252244fff29042926e21fa897ef5ab11148e35299John Reck    static void callOnFinished(OnFinishedEvent& event) {
11352244fff29042926e21fa897ef5ab11148e35299John Reck        event.listener->onAnimationFinished(event.animator.get());
114e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
115e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
116e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    virtual void handleMessage(const Message& message) {
11752244fff29042926e21fa897ef5ab11148e35299John Reck        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
11852244fff29042926e21fa897ef5ab11148e35299John Reck        mOnFinishedEvents.clear();
119e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
120e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
121e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckprivate:
12252244fff29042926e21fa897ef5ab11148e35299John Reck    std::vector<OnFinishedEvent> mOnFinishedEvents;
123e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck};
124e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
125c25e506f7fc08790c0532f927f31310a2ca778b7John Reckclass RenderingException : public MessageHandler {
126e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckpublic:
127c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    RenderingException(JavaVM* vm, const std::string& message)
128c25e506f7fc08790c0532f927f31310a2ca778b7John Reck            : mVm(vm)
129c25e506f7fc08790c0532f927f31310a2ca778b7John Reck            , mMessage(message) {
130c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    }
131c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
132c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    virtual void handleMessage(const Message&) {
133c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        throwException(mVm, mMessage);
134c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    }
135c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
136c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    static void throwException(JavaVM* vm, const std::string& message) {
137c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        JNIEnv* env = getenv(vm);
138c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
139c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    }
140c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
141c25e506f7fc08790c0532f927f31310a2ca778b7John Reckprivate:
142c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    JavaVM* mVm;
143c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    std::string mMessage;
144c25e506f7fc08790c0532f927f31310a2ca778b7John Reck};
145c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
14651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reckclass RootRenderNode : public RenderNode, ErrorHandler {
147c25e506f7fc08790c0532f927f31310a2ca778b7John Reckpublic:
148c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    RootRenderNode(JNIEnv* env) : RenderNode() {
149e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        mLooper = Looper::getForThread();
150e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
151e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck                "Must create RootRenderNode on a thread with a looper!");
152c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        env->GetJavaVM(&mVm);
153e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
154e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
155e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    virtual ~RootRenderNode() {}
156e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
15744b49f070aafe8ad44efae87341121cce49ff11cJohn Reck    virtual void onError(const std::string& message) override {
158c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        mLooper->sendMessage(new RenderingException(mVm, message), 0);
159c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    }
160c25e506f7fc08790c0532f927f31310a2ca778b7John Reck
16144b49f070aafe8ad44efae87341121cce49ff11cJohn Reck    virtual void prepareTree(TreeInfo& info) override {
162c25e506f7fc08790c0532f927f31310a2ca778b7John Reck        info.errorHandler = this;
163f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        // TODO: This is hacky
164f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.windowInsetLeft = -stagingProperties().getLeft();
165f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.windowInsetTop = -stagingProperties().getTop();
166f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.updateWindowPositions = true;
167e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        RenderNode::prepareTree(info);
168f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.updateWindowPositions = false;
169f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.windowInsetLeft = 0;
170f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        info.windowInsetTop = 0;
17144b49f070aafe8ad44efae87341121cce49ff11cJohn Reck        info.errorHandler = nullptr;
172119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
173119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
174119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    void sendMessage(const sp<MessageHandler>& handler) {
175119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        mLooper->sendMessage(handler, 0);
176119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
177119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
178119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    void attachAnimatingNode(RenderNode* animatingNode) {
179119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        mPendingAnimatingRenderNodes.push_back(animatingNode);
180119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
181119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
182119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    void doAttachAnimatingNodes(AnimationContext* context) {
183119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
184119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
185119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            context->addAnimatingRenderNode(*node);
186119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        }
187119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        mPendingAnimatingRenderNodes.clear();
188119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
189119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
190350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu    void destroy() {
191350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu        for (auto& renderNode : mPendingAnimatingRenderNodes) {
192350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu            renderNode->animators().endAllStagingAnimators();
193350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu        }
194350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu        mPendingAnimatingRenderNodes.clear();
195350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu    }
196350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu
197119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckprivate:
198119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    sp<Looper> mLooper;
199119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    JavaVM* mVm;
200119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
201119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck};
202119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
203119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckclass AnimationContextBridge : public AnimationContext {
204119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckpublic:
205119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
206119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            : AnimationContext(clock), mRootNode(rootNode) {
207119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
208119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
209119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    virtual ~AnimationContextBridge() {}
210e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
211119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    // Marks the start of a frame, which will update the frame time and move all
212119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    // next frame animations into the current frame
213ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck    virtual void startFrame(TreeInfo::TraversalMode mode) {
214ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck        if (mode == TreeInfo::MODE_FULL) {
215ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck            mRootNode->doAttachAnimatingNodes(this);
216ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck        }
217ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck        AnimationContext::startFrame(mode);
218119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
219119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
220119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    // Runs any animations still left in mCurrentFrameAnimations
221119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    virtual void runRemainingAnimations(TreeInfo& info) {
222119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        AnimationContext::runRemainingAnimations(info);
223e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        postOnFinishedEvents();
224e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
225e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
226119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
227119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        OnFinishedEvent event(animator, listener);
228119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        mOnFinishedEvents.push_back(event);
229119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
230119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
231e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    virtual void destroy() {
232e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        AnimationContext::destroy();
233e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        postOnFinishedEvents();
234e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    }
235e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
236e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckprivate:
237119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    sp<RootRenderNode> mRootNode;
23852244fff29042926e21fa897ef5ab11148e35299John Reck    std::vector<OnFinishedEvent> mOnFinishedEvents;
239e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
240e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    void postOnFinishedEvents() {
241e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        if (mOnFinishedEvents.size()) {
242e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            sp<InvokeAnimationListeners> message
243e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck                    = new InvokeAnimationListeners(mOnFinishedEvents);
244e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            mRootNode->sendMessage(message);
245e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        }
246e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    }
247119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck};
248119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
249119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckclass ContextFactoryImpl : public IContextFactory {
250119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckpublic:
251119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
252119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
253119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
254119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        return new AnimationContextBridge(clock, mRootNode);
255119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
256119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
257119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckprivate:
258119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    RootRenderNode* mRootNode;
259e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck};
260e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
26106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesclass ObserverProxy;
26206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
26306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesclass NotifyHandler : public MessageHandler {
26406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralespublic:
26511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {}
266910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales
26706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    virtual void handleMessage(const Message& message);
26806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
26906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesprivate:
27011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    JavaVM* const mVm;
27111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    ObserverProxy* const mObserver;
27206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales};
27306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
274910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Moralesstatic jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
275910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jobject frameMetrics = env->GetObjectField(
276910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            observer, gFrameMetricsObserverClassInfo.frameMetrics);
277910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
278910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jobject buffer = env->GetObjectField(
279910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
280910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
281910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    return reinterpret_cast<jlongArray>(buffer);
282910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales}
283910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales
28411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales/*
28511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales * Implements JNI layer for hwui frame metrics reporting.
28611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales */
287910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Moralesclass ObserverProxy : public FrameMetricsObserver {
28806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralespublic:
289910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
29006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        JNIEnv* env = getenv(mVm);
29106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
292910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        mObserverWeak = env->NewWeakGlobalRef(observer);
293910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
29406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales                "unable to create frame stats observer reference");
29506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
296910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        jlongArray buffer = get_metrics_buffer(env, observer);
297910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
298910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
299910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales                "Mismatched Java/Native FrameMetrics data format.");
300910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales
301910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        jobject messageQueueLocal = env->GetObjectField(
302910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales                observer, gFrameMetricsObserverClassInfo.messageQueue);
30306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
30406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
30506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
30611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        mMessageHandler = new NotifyHandler(mVm, this);
30706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
30806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales                "OOM: unable to allocate NotifyHandler");
30906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
31006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
31106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    ~ObserverProxy() {
31206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        JNIEnv* env = getenv(mVm);
313910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        env->DeleteWeakGlobalRef(mObserverWeak);
31406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
31506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
316910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jweak getObserverReference() {
317910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        return mObserverWeak;
31806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
31906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
32011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
32111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
32211f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
32311f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        if (elem.hasData.load()) {
32411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
32511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            *dropCount = elem.dropCount;
32611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            mNextInQueue = (mNextInQueue + 1) % kRingSize;
32711f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            elem.hasData = false;
32811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            return true;
32911f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        }
33011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
33111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        return false;
33211f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    }
33311f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
33411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    virtual void notify(const int64_t* stats) {
33511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        FrameMetricsNotification& elem = mRingBuffer[mNextFree];
33611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
33711f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        if (!elem.hasData.load()) {
33811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
33911f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
34011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            elem.dropCount = mDroppedReports;
34111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            mDroppedReports = 0;
34211f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
34311f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            incStrong(nullptr);
34411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            mNextFree = (mNextFree + 1) % kRingSize;
34511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            elem.hasData = true;
34611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
34711f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
34811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        } else {
34911f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            mDroppedReports++;
35011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        }
35106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
35206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
35306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesprivate:
35406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
35511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    static constexpr int kRingSize = 3;
35606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
35711f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    class FrameMetricsNotification {
35811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    public:
35911f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        FrameMetricsNotification() : hasData(false) {}
36011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
36111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        std::atomic_bool hasData;
36211f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        int64_t buffer[kBufferSize];
36311f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        int dropCount = 0;
36411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    };
36511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
36611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    JavaVM* const mVm;
367910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jweak mObserverWeak;
368910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jobject mJavaBufferGlobal;
36906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
37006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    sp<MessageQueue> mMessageQueue;
37106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    sp<NotifyHandler> mMessageHandler;
37206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    Message mMessage;
373910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales
37411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    int mNextFree = 0;
37511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    int mNextInQueue = 0;
37611f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    FrameMetricsNotification mRingBuffer[kRingSize];
37711f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales
37811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    int mDroppedReports = 0;
37906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales};
38006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
38106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Moralesvoid NotifyHandler::handleMessage(const Message& message) {
38206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    JNIEnv* env = getenv(mVm);
38306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
38411f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    jobject target = env->NewLocalRef(mObserver->getObserverReference());
38506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
38606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    if (target != nullptr) {
387910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        jlongArray javaBuffer = get_metrics_buffer(env, target);
38811f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        int dropCount = 0;
38911f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
39011f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales            env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
39111f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales        }
392910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales        env->DeleteLocalRef(target);
39306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
39406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
39511f02d7e522ec8742f7ef533c252e04e24b93f6bAndres Morales    mObserver->decStrong(nullptr);
39606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales}
39706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
39866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckstatic void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
3993b20251a355c88193c439f928a84ae69483fb488John Reck        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
40066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
40166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    jsize len = env->GetArrayLength(atlasMapArray);
40266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    if (len <= 0) {
40366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
40466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        return;
40566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
40666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    int64_t* map = new int64_t[len];
40766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
40866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
4093b20251a355c88193c439f928a84ae69483fb488John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
4103b20251a355c88193c439f928a84ae69483fb488John Reck    proxy->setTextureAtlas(buffer, map, len);
4114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
413edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
414edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        jlong proxyPtr, jint fd) {
415edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
416edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    proxy->setProcessStatsBuffer(fd);
417edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
418edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
419e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckstatic jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
420c25e506f7fc08790c0532f927f31310a2ca778b7John Reck    RootRenderNode* node = new RootRenderNode(env);
421e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    node->incStrong(0);
422e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    node->setName("RootRenderNode");
423e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    return reinterpret_cast<jlong>(node);
424e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
425e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
4264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
427e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        jboolean translucent, jlong rootRenderNodePtr) {
428119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
429119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    ContextFactoryImpl factory(rootRenderNode);
430119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
4314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4324f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4334f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
4344f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr) {
43519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
4364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    delete proxy;
4374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
439e4280baaa709c74d86cf6a389a4674ca665f5af6John Reckstatic jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
440e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck        jlong proxyPtr) {
441e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
442e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    return proxy->loadSystemProperties();
443e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck}
444e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck
445b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reckstatic void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
446b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck        jlong proxyPtr, jstring jname) {
447b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
448b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck    const char* name = env->GetStringUTFChars(jname, NULL);
449b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck    proxy->setName(name);
450b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck    env->ReleaseStringUTFChars(jname, name);
451b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck}
452b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck
4530bcd0cb6b1193168fa2840855195347488daab9eThomas Buhotstatic void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
4544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr, jobject jsurface) {
45519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
456f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
457f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    proxy->initialize(surface);
4584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4604f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
4614f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr, jobject jsurface) {
46219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
463f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    sp<Surface> surface;
4644f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (jsurface) {
465f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        surface = android_view_Surface_getSurface(env, jsurface);
4664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
467f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    proxy->updateSurface(surface);
468f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck}
469f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
47001a5ea35fbba4c5bb1d7790ae1677a2fa752e042John Reckstatic jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
471f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        jlong proxyPtr, jobject jsurface) {
472f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
473f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    sp<Surface> surface;
474f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    if (jsurface) {
475f648108f83d4e74811919e9811efb8fcc184b8a3John Reck        surface = android_view_Surface_getSurface(env, jsurface);
476f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    }
477f648108f83d4e74811919e9811efb8fcc184b8a3John Reck    return proxy->pauseSurface(surface);
4784f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4794f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4808afcc76920499d0a384dba1470c5a377f80ed768John Reckstatic void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
4818afcc76920499d0a384dba1470c5a377f80ed768John Reck        jlong proxyPtr, jboolean stopped) {
4828afcc76920499d0a384dba1470c5a377f80ed768John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
4838afcc76920499d0a384dba1470c5a377f80ed768John Reck    proxy->setStopped(stopped);
4848afcc76920499d0a384dba1470c5a377f80ed768John Reck}
4858afcc76920499d0a384dba1470c5a377f80ed768John Reck
486797b95b26bbb7557678af78b9a2a61830158920fChris Craikstatic void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
48750210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette        jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
48819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
48950210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha);
49050210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette}
49150210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette
49250210d912925aef14e4ce69be82e4949122a3cd9Alan Viverettestatic void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
49350210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
49450210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
49550210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
4964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
49863a06673253914510bbeebd500655008682dade1John Reckstatic void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
49963a06673253914510bbeebd500655008682dade1John Reck        jlong proxyPtr, jboolean opaque) {
50063a06673253914510bbeebd500655008682dade1John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
50163a06673253914510bbeebd500655008682dade1John Reck    proxy->setOpaque(opaque);
50263a06673253914510bbeebd500655008682dade1John Reck}
50363a06673253914510bbeebd500655008682dade1John Reck
504f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reckstatic int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
50551f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
506ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
507ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck            "Mismatched size expectations, given %d expected %d",
508ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
50919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
51051f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ScopedRemovedRenderNodeObserver observer(env);
511ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
51251f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    return proxy->syncAndDrawFrame(&observer);
5134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
5144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
51517035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reckstatic void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
516350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu        jlong proxyPtr, jlong rootNodePtr) {
51751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ScopedRemovedRenderNodeObserver observer(env);
518350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
519350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu    rootRenderNode->destroy();
52019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
52151f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    proxy->destroy(&observer);
5224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
5234f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
524119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckstatic void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
525119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        jlong rootNodePtr, jlong animatingNodePtr) {
526119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
527119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
528119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    rootRenderNode->attachAnimatingNode(animatingNode);
529119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
530119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
5310d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckstatic void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
5323b20251a355c88193c439f928a84ae69483fb488John Reck        jlong functorPtr, jboolean waitForCompletion) {
5330d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
5343b20251a355c88193c439f928a84ae69483fb488John Reck    RenderProxy::invokeFunctor(functor, waitForCompletion);
5350d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
5360d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
53719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckstatic jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
53819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr) {
53919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
54019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = proxy->createTextureLayer();
54119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return reinterpret_cast<jlong>(layer);
54219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
54319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
5443e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reckstatic void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
5453e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck        jlong proxyPtr, jlong nodePtr) {
54651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ScopedRemovedRenderNodeObserver observer(env);
5473e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
5483e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
54951f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    proxy->buildLayer(node, &observer);
5503e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck}
5513e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
55219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckstatic jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
5533731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
55419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
55519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
5563731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
5573731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
55819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return proxy->copyLayerInto(layer, bitmap);
55919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
56019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
561d72e0a339b54af0c4e731513bbad120dff694723John Reckstatic void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
56219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr, jlong layerPtr) {
56319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
56419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
565d72e0a339b54af0c4e731513bbad120dff694723John Reck    proxy->pushLayerUpdate(layer);
566d72e0a339b54af0c4e731513bbad120dff694723John Reck}
567d72e0a339b54af0c4e731513bbad120dff694723John Reck
568d72e0a339b54af0c4e731513bbad120dff694723John Reckstatic void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
569d72e0a339b54af0c4e731513bbad120dff694723John Reck        jlong proxyPtr, jlong layerPtr) {
570d72e0a339b54af0c4e731513bbad120dff694723John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
571d72e0a339b54af0c4e731513bbad120dff694723John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
572d72e0a339b54af0c4e731513bbad120dff694723John Reck    proxy->cancelLayerUpdate(layer);
57319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
57419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
575918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reckstatic void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
576918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck        jlong proxyPtr, jlong layerPtr) {
577918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
578918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
579918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    proxy->detachSurfaceTexture(layer);
580918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck}
581918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck
582f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckstatic void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
583f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        jlong proxyPtr) {
58451f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    ScopedRemovedRenderNodeObserver observer(env);
585e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
58651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    proxy->destroyHardwareResources(&observer);
587f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck}
588f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
589f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckstatic void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
590f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        jint level) {
591f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    RenderProxy::trimMemory(level);
592e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck}
593e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck
5942507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craikstatic void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
5952507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        jstring name, jstring value) {
5962507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    const char* nameCharArray = env->GetStringUTFChars(name, NULL);
5972507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    const char* valueCharArray = env->GetStringUTFChars(value, NULL);
5982507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    RenderProxy::overrideProperty(nameCharArray, valueCharArray);
5992507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    env->ReleaseStringUTFChars(name, nameCharArray);
6002507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    env->ReleaseStringUTFChars(name, valueCharArray);
6012507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik}
6022507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik
60328ad7b52e038ef0cdd89f753d9839444a434b299John Reckstatic void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
60428ad7b52e038ef0cdd89f753d9839444a434b299John Reck        jlong proxyPtr) {
60528ad7b52e038ef0cdd89f753d9839444a434b299John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
60628ad7b52e038ef0cdd89f753d9839444a434b299John Reck    proxy->fence();
60728ad7b52e038ef0cdd89f753d9839444a434b299John Reck}
60828ad7b52e038ef0cdd89f753d9839444a434b299John Reck
609f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckstatic void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
610f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        jlong proxyPtr) {
611f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
612f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    proxy->stopDrawing();
613f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck}
614f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
615a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckstatic void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
616a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        jlong proxyPtr) {
617a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
618a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    proxy->notifyFramePending();
619a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck}
620a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
621e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckstatic void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
622e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        jlong proxyPtr) {
623e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
624e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    proxy->serializeDisplayListTree();
625e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck}
626e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
627fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
628ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
629fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
630fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
631ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    proxy->dumpProfileInfo(fd, dumpFlags);
632fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
633fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
634edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
635edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        jbyteArray jdata, jobject javaFileDescriptor) {
636edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
637edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    ScopedByteArrayRO buffer(env, jdata);
638edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (buffer.get()) {
639edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
640edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
641edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
642edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
643ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnestatic void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
644ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne        jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
645ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
646ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
647ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    proxy->addRenderNode(renderNode, placeFront);
648ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne}
649ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne
650ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnestatic void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
651ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne        jlong proxyPtr, jlong renderNodePtr) {
652ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
653ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
654ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    proxy->removeRenderNode(renderNode);
655ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne}
656ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne
657ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnestatic void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
658ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne        jlong proxyPtr, jlong renderNodePtr) {
659ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
660ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
661ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    proxy->drawRenderNode(renderNode);
662ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne}
663ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne
664b816087962aba0019b022303330f03b897b580edSkuhnestatic void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
665ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne        jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
666ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
667b816087962aba0019b022303330f03b897b580edSkuhne    proxy->setContentDrawBounds(left, top, right, bottom);
668ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne}
669edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
670e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reckstatic jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
67110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        jobject clazz, jobject jsurface, jobject jbitmap) {
67210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    SkBitmap bitmap;
67310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
67410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
67510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    return RenderProxy::copySurfaceInto(surface, &bitmap);
67610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck}
67710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
678cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// ----------------------------------------------------------------------------
679910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales// FrameMetricsObserver
68006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales// ----------------------------------------------------------------------------
68106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
682910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Moralesstatic jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
68306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        jclass clazz, jlong proxyPtr, jobject fso) {
68406f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    JavaVM* vm = nullptr;
68506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    if (env->GetJavaVM(&vm) != JNI_OK) {
68606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        LOG_ALWAYS_FATAL("Unable to get Java VM");
68706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        return 0;
68806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    }
68906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
69006f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    renderthread::RenderProxy* renderProxy =
69106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
69206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
693910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
694910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    renderProxy->addFrameMetricsObserver(observer);
69506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    return reinterpret_cast<jlong>(observer);
69606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales}
69706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
698910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Moralesstatic void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
69906f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales        jlong proxyPtr, jlong observerPtr) {
700910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
70106f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales    renderthread::RenderProxy* renderProxy =
70206f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
70306f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
704910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    renderProxy->removeFrameMetricsObserver(observer);
70506f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales}
70606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
70706f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales// ----------------------------------------------------------------------------
70884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// Shaders
70984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// ----------------------------------------------------------------------------
71084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
71184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reckstatic void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
71284a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        jstring diskCachePath) {
71384a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
71484a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    egl_cache_t::get()->setCacheFilename(cacheArray);
71584a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
71684a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck}
71784a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
71884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// ----------------------------------------------------------------------------
719cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// JNI Glue
720cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// ----------------------------------------------------------------------------
721cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
722cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckconst char* const kClassPathName = "android/view/ThreadedRenderer";
723cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
72476f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
7253b20251a355c88193c439f928a84ae69483fb488John Reck    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
726edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
727e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
728e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
7294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
730e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
731b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
7320bcd0cb6b1193168fa2840855195347488daab9eThomas Buhot    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
7334f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
73401a5ea35fbba4c5bb1d7790ae1677a2fa752e042John Reck    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
7358afcc76920499d0a384dba1470c5a377f80ed768John Reck    { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
73650210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
73750210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
73863a06673253914510bbeebd500655008682dade1John Reck    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
73951f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
740350e65206cfbd86484fcfda77bb988e270606ddaDoris Liu    { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
741119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
7423b20251a355c88193c439f928a84ae69483fb488John Reck    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
74319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
7443e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
7453731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
746d72e0a339b54af0c4e731513bbad120dff694723John Reck    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
747d72e0a339b54af0c4e731513bbad120dff694723John Reck    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
748918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
749f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
750f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
7512507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
75228ad7b52e038ef0cdd89f753d9839444a434b299John Reck    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
753f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
754a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
755e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
756ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
757edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
75884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
75984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
760ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
761ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
762ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
763b816087962aba0019b022303330f03b897b580edSkuhne    { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
764910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    { "nAddFrameMetricsObserver",
765910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            "(JLandroid/view/FrameMetricsObserver;)J",
766910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
767910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    { "nRemoveFrameMetricsObserver",
76806f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales            "(JJ)V",
769910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
770e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck    { "nCopySurfaceInto", "(Landroid/view/Surface;Landroid/graphics/Bitmap;)I",
77110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                (void*)android_view_ThreadedRenderer_copySurfaceInto },
772cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck};
773cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
774cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckint register_android_view_ThreadedRenderer(JNIEnv* env) {
775910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
776910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
777910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
778910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
779910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
780910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
781910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            env, observerClass, "notifyDataAvailable", "(I)V");
782910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales
783910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
784910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales    gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
785910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales            env, metricsClass, "mTimingData", "[J");
78606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales
787ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
788cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck}
789cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
790cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck}; // namespace android
791