android_view_ThreadedRenderer.cpp revision 84a4c887a07c1c2939443f4e0587d7f1ac109e4b
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>
20e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
21cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include "jni.h"
22cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <nativehelper/JNIHelp.h>
23cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <android_runtime/AndroidRuntime.h>
24cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
2584a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/egl.h>
2684a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/eglext.h>
2784a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck#include <EGL/egl_cache.h>
2884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <utils/StrongPointer.h>
304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <android_runtime/android_view_Surface.h>
314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <system/window.h>
324f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck#include "android_view_GraphicBuffer.h"
3466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
3552244fff29042926e21fa897ef5ab11148e35299John Reck#include <Animator.h>
36e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <RenderNode.h>
3766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck#include <renderthread/CanvasContext.h>
384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <renderthread/RenderProxy.h>
39cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <renderthread/RenderTask.h>
40cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#include <renderthread/RenderThread.h>
41797b95b26bbb7557678af78b9a2a61830158920fChris Craik#include <Vector.h>
42cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
43cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Recknamespace android {
44cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
45cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#ifdef USE_OPENGL_RENDERER
46cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
474f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckusing namespace android::uirenderer;
484f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckusing namespace android::uirenderer::renderthread;
49cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
50cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckstatic jmethodID gRunnableMethod;
51cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
524f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckclass JavaTask : public RenderTask {
53cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckpublic:
54cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    JavaTask(JNIEnv* env, jobject jrunnable) {
55cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        env->GetJavaVM(&mVm);
56cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        mRunnable = env->NewGlobalRef(jrunnable);
57cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
58cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
59cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    virtual void run() {
60cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        env()->CallVoidMethod(mRunnable, gRunnableMethod);
614f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        env()->DeleteGlobalRef(mRunnable);
624f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        delete this;
63cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    };
64cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
65cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckprivate:
66cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    JNIEnv* env() {
67cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        JNIEnv* env;
68cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
69cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck            return 0;
70cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        }
71cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        return env;
72cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
73cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
74cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    JavaVM* mVm;
75cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    jobject mRunnable;
76cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck};
77cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
7866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckclass SetAtlasTask : public RenderTask {
7966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckpublic:
8066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
8166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            : mBuffer(buffer)
8266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            , mMap(map)
8366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            , mMapSize(size) {
8466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
8566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
8666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    virtual void run() {
8766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
8866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        mMap = 0;
8966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        delete this;
9066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
9166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
9266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckprivate:
9366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    sp<GraphicBuffer> mBuffer;
9466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    int64_t* mMap;
9566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    size_t mMapSize;
9666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck};
9766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn 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
12552244fff29042926e21fa897ef5ab11148e35299John Reckclass RootRenderNode : public RenderNode, public AnimationHook {
126e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckpublic:
127e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    RootRenderNode() : RenderNode() {
128e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        mLooper = Looper::getForThread();
129e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
130e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck                "Must create RootRenderNode on a thread with a looper!");
131e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
132e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
133e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    virtual ~RootRenderNode() {}
134e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
135ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
13652244fff29042926e21fa897ef5ab11148e35299John Reck        OnFinishedEvent event(animator, listener);
13752244fff29042926e21fa897ef5ab11148e35299John Reck        mOnFinishedEvents.push_back(event);
138e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
139e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
140e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    virtual void prepareTree(TreeInfo& info) {
14152244fff29042926e21fa897ef5ab11148e35299John Reck        info.animationHook = this;
142e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        RenderNode::prepareTree(info);
14352244fff29042926e21fa897ef5ab11148e35299John Reck        info.animationHook = NULL;
144e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
145e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        // post all the finished stuff
14652244fff29042926e21fa897ef5ab11148e35299John Reck        if (mOnFinishedEvents.size()) {
147e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck            sp<InvokeAnimationListeners> message
14852244fff29042926e21fa897ef5ab11148e35299John Reck                    = new InvokeAnimationListeners(mOnFinishedEvents);
149e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck            mLooper->sendMessage(message, 0);
150e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        }
151e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
152e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
153e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckprivate:
154e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    sp<Looper> mLooper;
15552244fff29042926e21fa897ef5ab11148e35299John Reck    std::vector<OnFinishedEvent> mOnFinishedEvents;
156e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck};
157e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
15866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckstatic void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
15966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        jobject graphicBuffer, jlongArray atlasMapArray) {
16066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
16166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    jsize len = env->GetArrayLength(atlasMapArray);
16266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    if (len <= 0) {
16366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
16466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        return;
16566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
16666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    int64_t* map = new int64_t[len];
16766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
16866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
16966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
1704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    RenderThread::getInstance().queue(task);
1714f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
1724f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
173e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckstatic jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
174e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    RootRenderNode* node = new RootRenderNode();
175e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    node->incStrong(0);
176e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    node->setName("RootRenderNode");
177e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    return reinterpret_cast<jlong>(node);
178e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
179e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
1804f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
181e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        jboolean translucent, jlong rootRenderNodePtr) {
182e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr);
183e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    return (jlong) new RenderProxy(translucent, rootRenderNode);
1844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
1854f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
1874f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr) {
18819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
1894f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    delete proxy;
1904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
1914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
19218f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reckstatic void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
19318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck        jlong proxyPtr, jlong frameIntervalNanos) {
19418f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
19518f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    proxy->setFrameInterval(frameIntervalNanos);
19618f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck}
19718f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck
198e4280baaa709c74d86cf6a389a4674ca665f5af6John Reckstatic jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
199e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck        jlong proxyPtr) {
200e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
201e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    return proxy->loadSystemProperties();
202e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck}
203e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck
2044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
2054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr, jobject jsurface) {
20619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
2074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
208f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    return proxy->initialize(window);
2094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckstatic void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
2124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr, jobject jsurface) {
21319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
2144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    sp<ANativeWindow> window;
2154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (jsurface) {
2164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        window = android_view_Surface_getNativeWindow(env, jsurface);
2174f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
218f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    proxy->updateSurface(window);
219f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck}
220f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
221f7d9c1dc84671d4e99657ef071d275700d85bb11John Reckstatic void android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
222f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        jlong proxyPtr, jobject jsurface) {
223f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
224f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    sp<ANativeWindow> window;
225f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    if (jsurface) {
226f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        window = android_view_Surface_getNativeWindow(env, jsurface);
227f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    }
228f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    proxy->pauseSurface(window);
2294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
231797b95b26bbb7557678af78b9a2a61830158920fChris Craikstatic void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
232797b95b26bbb7557678af78b9a2a61830158920fChris Craik        jint width, jint height,
233797b95b26bbb7557678af78b9a2a61830158920fChris Craik        jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
23419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
235797b95b26bbb7557678af78b9a2a61830158920fChris Craik    proxy->setup(width, height, Vector3(lightX, lightY, lightZ), lightRadius);
2364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
23863a06673253914510bbeebd500655008682dade1John Reckstatic void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
23963a06673253914510bbeebd500655008682dade1John Reck        jlong proxyPtr, jboolean opaque) {
24063a06673253914510bbeebd500655008682dade1John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
24163a06673253914510bbeebd500655008682dade1John Reck    proxy->setOpaque(opaque);
24263a06673253914510bbeebd500655008682dade1John Reck}
24363a06673253914510bbeebd500655008682dade1John Reck
244f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reckstatic int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
245fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density,
246fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        jint dirtyLeft, jint dirtyTop, jint dirtyRight, jint dirtyBottom) {
24719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density,
249fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
2504f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2514f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
252fae904d63947fe1687d1d44be29234cc3d538f24John Reckstatic void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
2534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        jlong proxyPtr) {
25419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
255fae904d63947fe1687d1d44be29234cc3d538f24John Reck    proxy->destroyCanvasAndSurface();
2564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2574f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2580d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckstatic void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
2590d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
2600d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
2610d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
2620d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    proxy->invokeFunctor(functor, waitForCompletion);
2630d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
2640d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
265fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reckstatic void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
266fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        jlong proxyPtr, jobject jrunnable) {
26719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
268fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    RenderTask* task = new JavaTask(env, jrunnable);
269fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    proxy->runWithGlContext(task);
270fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck}
271fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck
27219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckstatic jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz,
27319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr, jint width, jint height) {
27419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
27519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height);
27619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return reinterpret_cast<jlong>(layer);
27719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
27819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
27919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckstatic jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
28019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr) {
28119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
28219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = proxy->createTextureLayer();
28319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return reinterpret_cast<jlong>(layer);
28419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
28519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
28619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckstatic jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
28719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
28819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
28919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
29019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
29119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return proxy->copyLayerInto(layer, bitmap);
29219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
29319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
294d72e0a339b54af0c4e731513bbad120dff694723John Reckstatic void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
29519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        jlong proxyPtr, jlong layerPtr) {
29619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
29719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
298d72e0a339b54af0c4e731513bbad120dff694723John Reck    proxy->pushLayerUpdate(layer);
299d72e0a339b54af0c4e731513bbad120dff694723John Reck}
300d72e0a339b54af0c4e731513bbad120dff694723John Reck
301d72e0a339b54af0c4e731513bbad120dff694723John Reckstatic void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
302d72e0a339b54af0c4e731513bbad120dff694723John Reck        jlong proxyPtr, jlong layerPtr) {
303d72e0a339b54af0c4e731513bbad120dff694723John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
304d72e0a339b54af0c4e731513bbad120dff694723John Reck    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
305d72e0a339b54af0c4e731513bbad120dff694723John Reck    proxy->cancelLayerUpdate(layer);
30619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
30719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
308e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reckstatic void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz,
309e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck        jlong proxyPtr, jint flushMode) {
310e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
311e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck    proxy->flushCaches(static_cast<Caches::FlushMode>(flushMode));
312e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck}
313e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck
31428ad7b52e038ef0cdd89f753d9839444a434b299John Reckstatic void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
31528ad7b52e038ef0cdd89f753d9839444a434b299John Reck        jlong proxyPtr) {
31628ad7b52e038ef0cdd89f753d9839444a434b299John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
31728ad7b52e038ef0cdd89f753d9839444a434b299John Reck    proxy->fence();
31828ad7b52e038ef0cdd89f753d9839444a434b299John Reck}
31928ad7b52e038ef0cdd89f753d9839444a434b299John Reck
320a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckstatic void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
321a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        jlong proxyPtr) {
322a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
323a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    proxy->notifyFramePending();
324a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck}
325a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
326fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
327fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        jlong proxyPtr, jobject javaFileDescriptor) {
328fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
329fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
330fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    proxy->dumpProfileInfo(fd);
331fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
332fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
333cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#endif
334cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
335cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// ----------------------------------------------------------------------------
33684a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// Shaders
33784a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// ----------------------------------------------------------------------------
33884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
33984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reckstatic void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
34084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        jstring diskCachePath) {
34184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
34284a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
34384a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    egl_cache_t::get()->setCacheFilename(cacheArray);
34484a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
34584a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck}
34684a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
34784a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck// ----------------------------------------------------------------------------
348cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// JNI Glue
349cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck// ----------------------------------------------------------------------------
350cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
351cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckconst char* const kClassPathName = "android/view/ThreadedRenderer";
352cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
353cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckstatic JNINativeMethod gMethods[] = {
354cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#ifdef USE_OPENGL_RENDERER
35566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
356e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
357e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
3584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
35918f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
360e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
3614f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
3624f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
363f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
364797b95b26bbb7557678af78b9a2a61830158920fChris Craik    { "nSetup", "(JIIFFFF)V", (void*) android_view_ThreadedRenderer_setup },
36563a06673253914510bbeebd500655008682dade1John Reck    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
366fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    { "nSyncAndDrawFrame", "(JJJFIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
367fae904d63947fe1687d1d44be29234cc3d538f24John Reck    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
3680d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
369fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
37019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
37119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
37219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
373d72e0a339b54af0c4e731513bbad120dff694723John Reck    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
374d72e0a339b54af0c4e731513bbad120dff694723John Reck    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
375e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck    { "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches },
37628ad7b52e038ef0cdd89f753d9839444a434b299John Reck    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
377a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
378fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
379cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#endif
38084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
38184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
382cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck};
383cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
384cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckint register_android_view_ThreadedRenderer(JNIEnv* env) {
385cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#ifdef USE_OPENGL_RENDERER
386cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    jclass cls = env->FindClass("java/lang/Runnable");
387cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    gRunnableMethod = env->GetMethodID(cls, "run", "()V");
388cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    env->DeleteLocalRef(cls);
389cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck#endif
390cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
391cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck}
392cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
393cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck}; // namespace android
394