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