Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "ThreadedRenderer"
     18 
     19 #include <algorithm>
     20 #include <atomic>
     21 
     22 #include "jni.h"
     23 #include <nativehelper/JNIHelp.h>
     24 #include "core_jni_helpers.h"
     25 #include <GraphicsJNI.h>
     26 #include <ScopedPrimitiveArray.h>
     27 
     28 #include <EGL/egl.h>
     29 #include <EGL/eglext.h>
     30 #include <EGL/egl_cache.h>
     31 
     32 #include <utils/Looper.h>
     33 #include <utils/RefBase.h>
     34 #include <utils/StrongPointer.h>
     35 #include <android_runtime/android_view_Surface.h>
     36 #include <system/window.h>
     37 
     38 #include "android_view_GraphicBuffer.h"
     39 #include "android_os_MessageQueue.h"
     40 
     41 #include <Animator.h>
     42 #include <AnimationContext.h>
     43 #include <FrameInfo.h>
     44 #include <FrameMetricsObserver.h>
     45 #include <IContextFactory.h>
     46 #include <JankTracker.h>
     47 #include <RenderNode.h>
     48 #include <renderthread/CanvasContext.h>
     49 #include <renderthread/RenderProxy.h>
     50 #include <renderthread/RenderTask.h>
     51 #include <renderthread/RenderThread.h>
     52 
     53 namespace android {
     54 
     55 using namespace android::uirenderer;
     56 using namespace android::uirenderer::renderthread;
     57 
     58 struct {
     59     jfieldID frameMetrics;
     60     jfieldID timingDataBuffer;
     61     jfieldID messageQueue;
     62     jmethodID callback;
     63 } gFrameMetricsObserverClassInfo;
     64 
     65 static JNIEnv* getenv(JavaVM* vm) {
     66     JNIEnv* env;
     67     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
     68         LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
     69     }
     70     return env;
     71 }
     72 
     73 // TODO: Clean this up, it's a bit odd to need to call over to
     74 // rendernode's jni layer. Probably means RootRenderNode should be pulled
     75 // into HWUI with appropriate callbacks for the various JNI hooks so
     76 // that RenderNode's JNI layer can handle its own thing
     77 void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
     78 
     79 class ScopedRemovedRenderNodeObserver : public TreeObserver {
     80 public:
     81     ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
     82     ~ScopedRemovedRenderNodeObserver() {
     83         for (auto& node : mMaybeRemovedNodes) {
     84             if (node->hasParents()) continue;
     85             onRenderNodeRemoved(mEnv, node.get());
     86         }
     87     }
     88 
     89     virtual void onMaybeRemovedFromTree(RenderNode* node) override {
     90         mMaybeRemovedNodes.insert(sp<RenderNode>(node));
     91     }
     92 
     93 private:
     94     JNIEnv* mEnv;
     95     std::set< sp<RenderNode> > mMaybeRemovedNodes;
     96 };
     97 
     98 class OnFinishedEvent {
     99 public:
    100     OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
    101             : animator(animator), listener(listener) {}
    102     sp<BaseRenderNodeAnimator> animator;
    103     sp<AnimationListener> listener;
    104 };
    105 
    106 class InvokeAnimationListeners : public MessageHandler {
    107 public:
    108     InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
    109         mOnFinishedEvents.swap(events);
    110     }
    111 
    112     static void callOnFinished(OnFinishedEvent& event) {
    113         event.listener->onAnimationFinished(event.animator.get());
    114     }
    115 
    116     virtual void handleMessage(const Message& message) {
    117         std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
    118         mOnFinishedEvents.clear();
    119     }
    120 
    121 private:
    122     std::vector<OnFinishedEvent> mOnFinishedEvents;
    123 };
    124 
    125 class RenderingException : public MessageHandler {
    126 public:
    127     RenderingException(JavaVM* vm, const std::string& message)
    128             : mVm(vm)
    129             , mMessage(message) {
    130     }
    131 
    132     virtual void handleMessage(const Message&) {
    133         throwException(mVm, mMessage);
    134     }
    135 
    136     static void throwException(JavaVM* vm, const std::string& message) {
    137         JNIEnv* env = getenv(vm);
    138         jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
    139     }
    140 
    141 private:
    142     JavaVM* mVm;
    143     std::string mMessage;
    144 };
    145 
    146 class RootRenderNode : public RenderNode, ErrorHandler {
    147 public:
    148     RootRenderNode(JNIEnv* env) : RenderNode() {
    149         mLooper = Looper::getForThread();
    150         LOG_ALWAYS_FATAL_IF(!mLooper.get(),
    151                 "Must create RootRenderNode on a thread with a looper!");
    152         env->GetJavaVM(&mVm);
    153     }
    154 
    155     virtual ~RootRenderNode() {}
    156 
    157     virtual void onError(const std::string& message) override {
    158         mLooper->sendMessage(new RenderingException(mVm, message), 0);
    159     }
    160 
    161     virtual void prepareTree(TreeInfo& info) override {
    162         info.errorHandler = this;
    163         // TODO: This is hacky
    164         info.windowInsetLeft = -stagingProperties().getLeft();
    165         info.windowInsetTop = -stagingProperties().getTop();
    166         info.updateWindowPositions = true;
    167         RenderNode::prepareTree(info);
    168         info.updateWindowPositions = false;
    169         info.windowInsetLeft = 0;
    170         info.windowInsetTop = 0;
    171         info.errorHandler = nullptr;
    172     }
    173 
    174     void sendMessage(const sp<MessageHandler>& handler) {
    175         mLooper->sendMessage(handler, 0);
    176     }
    177 
    178     void attachAnimatingNode(RenderNode* animatingNode) {
    179         mPendingAnimatingRenderNodes.push_back(animatingNode);
    180     }
    181 
    182     void doAttachAnimatingNodes(AnimationContext* context) {
    183         for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
    184             RenderNode* node = mPendingAnimatingRenderNodes[i].get();
    185             context->addAnimatingRenderNode(*node);
    186         }
    187         mPendingAnimatingRenderNodes.clear();
    188     }
    189 
    190     void destroy() {
    191         for (auto& renderNode : mPendingAnimatingRenderNodes) {
    192             renderNode->animators().endAllStagingAnimators();
    193         }
    194         mPendingAnimatingRenderNodes.clear();
    195     }
    196 
    197 private:
    198     sp<Looper> mLooper;
    199     JavaVM* mVm;
    200     std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
    201 };
    202 
    203 class AnimationContextBridge : public AnimationContext {
    204 public:
    205     AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
    206             : AnimationContext(clock), mRootNode(rootNode) {
    207     }
    208 
    209     virtual ~AnimationContextBridge() {}
    210 
    211     // Marks the start of a frame, which will update the frame time and move all
    212     // next frame animations into the current frame
    213     virtual void startFrame(TreeInfo::TraversalMode mode) {
    214         if (mode == TreeInfo::MODE_FULL) {
    215             mRootNode->doAttachAnimatingNodes(this);
    216         }
    217         AnimationContext::startFrame(mode);
    218     }
    219 
    220     // Runs any animations still left in mCurrentFrameAnimations
    221     virtual void runRemainingAnimations(TreeInfo& info) {
    222         AnimationContext::runRemainingAnimations(info);
    223         postOnFinishedEvents();
    224     }
    225 
    226     virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
    227         OnFinishedEvent event(animator, listener);
    228         mOnFinishedEvents.push_back(event);
    229     }
    230 
    231     virtual void destroy() {
    232         AnimationContext::destroy();
    233         postOnFinishedEvents();
    234     }
    235 
    236 private:
    237     sp<RootRenderNode> mRootNode;
    238     std::vector<OnFinishedEvent> mOnFinishedEvents;
    239 
    240     void postOnFinishedEvents() {
    241         if (mOnFinishedEvents.size()) {
    242             sp<InvokeAnimationListeners> message
    243                     = new InvokeAnimationListeners(mOnFinishedEvents);
    244             mRootNode->sendMessage(message);
    245         }
    246     }
    247 };
    248 
    249 class ContextFactoryImpl : public IContextFactory {
    250 public:
    251     ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
    252 
    253     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
    254         return new AnimationContextBridge(clock, mRootNode);
    255     }
    256 
    257 private:
    258     RootRenderNode* mRootNode;
    259 };
    260 
    261 class ObserverProxy;
    262 
    263 class NotifyHandler : public MessageHandler {
    264 public:
    265     NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {}
    266 
    267     virtual void handleMessage(const Message& message);
    268 
    269 private:
    270     JavaVM* const mVm;
    271     ObserverProxy* const mObserver;
    272 };
    273 
    274 static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
    275     jobject frameMetrics = env->GetObjectField(
    276             observer, gFrameMetricsObserverClassInfo.frameMetrics);
    277     LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
    278     jobject buffer = env->GetObjectField(
    279             frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
    280     LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
    281     return reinterpret_cast<jlongArray>(buffer);
    282 }
    283 
    284 /*
    285  * Implements JNI layer for hwui frame metrics reporting.
    286  */
    287 class ObserverProxy : public FrameMetricsObserver {
    288 public:
    289     ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
    290         JNIEnv* env = getenv(mVm);
    291 
    292         mObserverWeak = env->NewWeakGlobalRef(observer);
    293         LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
    294                 "unable to create frame stats observer reference");
    295 
    296         jlongArray buffer = get_metrics_buffer(env, observer);
    297         jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
    298         LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
    299                 "Mismatched Java/Native FrameMetrics data format.");
    300 
    301         jobject messageQueueLocal = env->GetObjectField(
    302                 observer, gFrameMetricsObserverClassInfo.messageQueue);
    303         mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
    304         LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
    305 
    306         mMessageHandler = new NotifyHandler(mVm, this);
    307         LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
    308                 "OOM: unable to allocate NotifyHandler");
    309     }
    310 
    311     ~ObserverProxy() {
    312         JNIEnv* env = getenv(mVm);
    313         env->DeleteWeakGlobalRef(mObserverWeak);
    314     }
    315 
    316     jweak getObserverReference() {
    317         return mObserverWeak;
    318     }
    319 
    320     bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
    321         FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
    322 
    323         if (elem.hasData.load()) {
    324             env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
    325             *dropCount = elem.dropCount;
    326             mNextInQueue = (mNextInQueue + 1) % kRingSize;
    327             elem.hasData = false;
    328             return true;
    329         }
    330 
    331         return false;
    332     }
    333 
    334     virtual void notify(const int64_t* stats) {
    335         FrameMetricsNotification& elem = mRingBuffer[mNextFree];
    336 
    337         if (!elem.hasData.load()) {
    338             memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
    339 
    340             elem.dropCount = mDroppedReports;
    341             mDroppedReports = 0;
    342 
    343             incStrong(nullptr);
    344             mNextFree = (mNextFree + 1) % kRingSize;
    345             elem.hasData = true;
    346 
    347             mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
    348         } else {
    349             mDroppedReports++;
    350         }
    351     }
    352 
    353 private:
    354     static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
    355     static constexpr int kRingSize = 3;
    356 
    357     class FrameMetricsNotification {
    358     public:
    359         FrameMetricsNotification() : hasData(false) {}
    360 
    361         std::atomic_bool hasData;
    362         int64_t buffer[kBufferSize];
    363         int dropCount = 0;
    364     };
    365 
    366     JavaVM* const mVm;
    367     jweak mObserverWeak;
    368     jobject mJavaBufferGlobal;
    369 
    370     sp<MessageQueue> mMessageQueue;
    371     sp<NotifyHandler> mMessageHandler;
    372     Message mMessage;
    373 
    374     int mNextFree = 0;
    375     int mNextInQueue = 0;
    376     FrameMetricsNotification mRingBuffer[kRingSize];
    377 
    378     int mDroppedReports = 0;
    379 };
    380 
    381 void NotifyHandler::handleMessage(const Message& message) {
    382     JNIEnv* env = getenv(mVm);
    383 
    384     jobject target = env->NewLocalRef(mObserver->getObserverReference());
    385 
    386     if (target != nullptr) {
    387         jlongArray javaBuffer = get_metrics_buffer(env, target);
    388         int dropCount = 0;
    389         while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
    390             env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
    391         }
    392         env->DeleteLocalRef(target);
    393     }
    394 
    395     mObserver->decStrong(nullptr);
    396 }
    397 
    398 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
    399         jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
    400     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
    401     jsize len = env->GetArrayLength(atlasMapArray);
    402     if (len <= 0) {
    403         ALOGW("Failed to initialize atlas, invalid map length: %d", len);
    404         return;
    405     }
    406     int64_t* map = new int64_t[len];
    407     env->GetLongArrayRegion(atlasMapArray, 0, len, map);
    408 
    409     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    410     proxy->setTextureAtlas(buffer, map, len);
    411 }
    412 
    413 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
    414         jlong proxyPtr, jint fd) {
    415     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    416     proxy->setProcessStatsBuffer(fd);
    417 }
    418 
    419 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
    420     RootRenderNode* node = new RootRenderNode(env);
    421     node->incStrong(0);
    422     node->setName("RootRenderNode");
    423     return reinterpret_cast<jlong>(node);
    424 }
    425 
    426 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
    427         jboolean translucent, jlong rootRenderNodePtr) {
    428     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
    429     ContextFactoryImpl factory(rootRenderNode);
    430     return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
    431 }
    432 
    433 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
    434         jlong proxyPtr) {
    435     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    436     delete proxy;
    437 }
    438 
    439 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
    440         jlong proxyPtr) {
    441     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    442     return proxy->loadSystemProperties();
    443 }
    444 
    445 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
    446         jlong proxyPtr, jstring jname) {
    447     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    448     const char* name = env->GetStringUTFChars(jname, NULL);
    449     proxy->setName(name);
    450     env->ReleaseStringUTFChars(jname, name);
    451 }
    452 
    453 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
    454         jlong proxyPtr, jobject jsurface) {
    455     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    456     sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
    457     proxy->initialize(surface);
    458 }
    459 
    460 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
    461         jlong proxyPtr, jobject jsurface) {
    462     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    463     sp<Surface> surface;
    464     if (jsurface) {
    465         surface = android_view_Surface_getSurface(env, jsurface);
    466     }
    467     proxy->updateSurface(surface);
    468 }
    469 
    470 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
    471         jlong proxyPtr, jobject jsurface) {
    472     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    473     sp<Surface> surface;
    474     if (jsurface) {
    475         surface = android_view_Surface_getSurface(env, jsurface);
    476     }
    477     return proxy->pauseSurface(surface);
    478 }
    479 
    480 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
    481         jlong proxyPtr, jboolean stopped) {
    482     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    483     proxy->setStopped(stopped);
    484 }
    485 
    486 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
    487         jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
    488     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    489     proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha);
    490 }
    491 
    492 static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
    493         jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
    494     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    495     proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
    496 }
    497 
    498 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
    499         jlong proxyPtr, jboolean opaque) {
    500     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    501     proxy->setOpaque(opaque);
    502 }
    503 
    504 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
    505         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
    506     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
    507             "Mismatched size expectations, given %d expected %d",
    508             frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
    509     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    510     ScopedRemovedRenderNodeObserver observer(env);
    511     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
    512     return proxy->syncAndDrawFrame(&observer);
    513 }
    514 
    515 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
    516         jlong proxyPtr, jlong rootNodePtr) {
    517     ScopedRemovedRenderNodeObserver observer(env);
    518     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
    519     rootRenderNode->destroy();
    520     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    521     proxy->destroy(&observer);
    522 }
    523 
    524 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
    525         jlong rootNodePtr, jlong animatingNodePtr) {
    526     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
    527     RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
    528     rootRenderNode->attachAnimatingNode(animatingNode);
    529 }
    530 
    531 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
    532         jlong functorPtr, jboolean waitForCompletion) {
    533     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
    534     RenderProxy::invokeFunctor(functor, waitForCompletion);
    535 }
    536 
    537 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
    538         jlong proxyPtr) {
    539     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    540     DeferredLayerUpdater* layer = proxy->createTextureLayer();
    541     return reinterpret_cast<jlong>(layer);
    542 }
    543 
    544 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
    545         jlong proxyPtr, jlong nodePtr) {
    546     ScopedRemovedRenderNodeObserver observer(env);
    547     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    548     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
    549     proxy->buildLayer(node, &observer);
    550 }
    551 
    552 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
    553         jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
    554     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    555     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    556     SkBitmap bitmap;
    557     GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
    558     return proxy->copyLayerInto(layer, bitmap);
    559 }
    560 
    561 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
    562         jlong proxyPtr, jlong layerPtr) {
    563     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    564     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    565     proxy->pushLayerUpdate(layer);
    566 }
    567 
    568 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
    569         jlong proxyPtr, jlong layerPtr) {
    570     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    571     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    572     proxy->cancelLayerUpdate(layer);
    573 }
    574 
    575 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
    576         jlong proxyPtr, jlong layerPtr) {
    577     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    578     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    579     proxy->detachSurfaceTexture(layer);
    580 }
    581 
    582 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
    583         jlong proxyPtr) {
    584     ScopedRemovedRenderNodeObserver observer(env);
    585     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    586     proxy->destroyHardwareResources(&observer);
    587 }
    588 
    589 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
    590         jint level) {
    591     RenderProxy::trimMemory(level);
    592 }
    593 
    594 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
    595         jstring name, jstring value) {
    596     const char* nameCharArray = env->GetStringUTFChars(name, NULL);
    597     const char* valueCharArray = env->GetStringUTFChars(value, NULL);
    598     RenderProxy::overrideProperty(nameCharArray, valueCharArray);
    599     env->ReleaseStringUTFChars(name, nameCharArray);
    600     env->ReleaseStringUTFChars(name, valueCharArray);
    601 }
    602 
    603 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
    604         jlong proxyPtr) {
    605     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    606     proxy->fence();
    607 }
    608 
    609 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
    610         jlong proxyPtr) {
    611     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    612     proxy->stopDrawing();
    613 }
    614 
    615 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
    616         jlong proxyPtr) {
    617     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    618     proxy->notifyFramePending();
    619 }
    620 
    621 static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
    622         jlong proxyPtr) {
    623     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    624     proxy->serializeDisplayListTree();
    625 }
    626 
    627 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
    628         jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
    629     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    630     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
    631     proxy->dumpProfileInfo(fd, dumpFlags);
    632 }
    633 
    634 static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
    635         jbyteArray jdata, jobject javaFileDescriptor) {
    636     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
    637     ScopedByteArrayRO buffer(env, jdata);
    638     if (buffer.get()) {
    639         JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
    640     }
    641 }
    642 
    643 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
    644         jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
    645     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    646     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    647     proxy->addRenderNode(renderNode, placeFront);
    648 }
    649 
    650 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
    651         jlong proxyPtr, jlong renderNodePtr) {
    652     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    653     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    654     proxy->removeRenderNode(renderNode);
    655 }
    656 
    657 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
    658         jlong proxyPtr, jlong renderNodePtr) {
    659     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    660     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    661     proxy->drawRenderNode(renderNode);
    662 }
    663 
    664 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
    665         jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
    666     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    667     proxy->setContentDrawBounds(left, top, right, bottom);
    668 }
    669 
    670 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
    671         jobject clazz, jobject jsurface, jobject jbitmap) {
    672     SkBitmap bitmap;
    673     GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
    674     sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
    675     return RenderProxy::copySurfaceInto(surface, &bitmap);
    676 }
    677 
    678 // ----------------------------------------------------------------------------
    679 // FrameMetricsObserver
    680 // ----------------------------------------------------------------------------
    681 
    682 static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
    683         jclass clazz, jlong proxyPtr, jobject fso) {
    684     JavaVM* vm = nullptr;
    685     if (env->GetJavaVM(&vm) != JNI_OK) {
    686         LOG_ALWAYS_FATAL("Unable to get Java VM");
    687         return 0;
    688     }
    689 
    690     renderthread::RenderProxy* renderProxy =
    691             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
    692 
    693     FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
    694     renderProxy->addFrameMetricsObserver(observer);
    695     return reinterpret_cast<jlong>(observer);
    696 }
    697 
    698 static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
    699         jlong proxyPtr, jlong observerPtr) {
    700     FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
    701     renderthread::RenderProxy* renderProxy =
    702             reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
    703 
    704     renderProxy->removeFrameMetricsObserver(observer);
    705 }
    706 
    707 // ----------------------------------------------------------------------------
    708 // Shaders
    709 // ----------------------------------------------------------------------------
    710 
    711 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
    712         jstring diskCachePath) {
    713     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
    714     egl_cache_t::get()->setCacheFilename(cacheArray);
    715     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
    716 }
    717 
    718 // ----------------------------------------------------------------------------
    719 // JNI Glue
    720 // ----------------------------------------------------------------------------
    721 
    722 const char* const kClassPathName = "android/view/ThreadedRenderer";
    723 
    724 static const JNINativeMethod gMethods[] = {
    725     { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
    726     { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
    727     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
    728     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
    729     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
    730     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
    731     { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
    732     { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
    733     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
    734     { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
    735     { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
    736     { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
    737     { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
    738     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
    739     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
    740     { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
    741     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
    742     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
    743     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
    744     { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
    745     { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
    746     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
    747     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
    748     { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
    749     { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
    750     { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
    751     { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
    752     { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
    753     { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
    754     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
    755     { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
    756     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
    757     { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
    758     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
    759                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
    760     { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
    761     { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
    762     { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
    763     { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
    764     { "nAddFrameMetricsObserver",
    765             "(JLandroid/view/FrameMetricsObserver;)J",
    766             (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
    767     { "nRemoveFrameMetricsObserver",
    768             "(JJ)V",
    769             (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
    770     { "nCopySurfaceInto", "(Landroid/view/Surface;Landroid/graphics/Bitmap;)I",
    771                 (void*)android_view_ThreadedRenderer_copySurfaceInto },
    772 };
    773 
    774 int register_android_view_ThreadedRenderer(JNIEnv* env) {
    775     jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
    776     gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
    777             env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
    778     gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
    779             env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
    780     gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
    781             env, observerClass, "notifyDataAvailable", "(I)V");
    782 
    783     jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
    784     gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
    785             env, metricsClass, "mTimingData", "[J");
    786 
    787     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
    788 }
    789 
    790 }; // namespace android
    791