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 #define ATRACE_TAG ATRACE_TAG_VIEW 19 20 #include <algorithm> 21 #include <atomic> 22 #include <inttypes.h> 23 24 #include "jni.h" 25 #include <nativehelper/JNIHelp.h> 26 #include "core_jni_helpers.h" 27 #include <GraphicsJNI.h> 28 #include <nativehelper/ScopedPrimitiveArray.h> 29 30 #include <gui/BufferItemConsumer.h> 31 #include <gui/BufferQueue.h> 32 #include <gui/Surface.h> 33 34 #include <EGL/egl.h> 35 #include <EGL/eglext.h> 36 #include <private/EGL/cache.h> 37 38 #include <utils/Looper.h> 39 #include <utils/RefBase.h> 40 #include <utils/StrongPointer.h> 41 #include <utils/Timers.h> 42 #include <utils/TraceUtils.h> 43 #include <android_runtime/android_view_Surface.h> 44 #include <system/window.h> 45 46 #include "android_os_MessageQueue.h" 47 48 #include <Animator.h> 49 #include <AnimationContext.h> 50 #include <FrameInfo.h> 51 #include <FrameMetricsObserver.h> 52 #include <IContextFactory.h> 53 #include <Properties.h> 54 #include <PropertyValuesAnimatorSet.h> 55 #include <RenderNode.h> 56 #include <renderthread/CanvasContext.h> 57 #include <renderthread/RenderProxy.h> 58 #include <renderthread/RenderTask.h> 59 #include <renderthread/RenderThread.h> 60 #include <pipeline/skia/ShaderCache.h> 61 62 namespace android { 63 64 using namespace android::uirenderer; 65 using namespace android::uirenderer::renderthread; 66 67 struct { 68 jfieldID frameMetrics; 69 jfieldID timingDataBuffer; 70 jfieldID messageQueue; 71 jmethodID callback; 72 } gFrameMetricsObserverClassInfo; 73 74 struct { 75 jmethodID onFrameDraw; 76 } gFrameDrawingCallback; 77 78 struct { 79 jmethodID onFrameComplete; 80 } gFrameCompleteCallback; 81 82 static JNIEnv* getenv(JavaVM* vm) { 83 JNIEnv* env; 84 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 85 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); 86 } 87 return env; 88 } 89 90 class OnFinishedEvent { 91 public: 92 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) 93 : animator(animator), listener(listener) {} 94 sp<BaseRenderNodeAnimator> animator; 95 sp<AnimationListener> listener; 96 }; 97 98 class InvokeAnimationListeners : public MessageHandler { 99 public: 100 explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) { 101 mOnFinishedEvents.swap(events); 102 } 103 104 static void callOnFinished(OnFinishedEvent& event) { 105 event.listener->onAnimationFinished(event.animator.get()); 106 } 107 108 virtual void handleMessage(const Message& message) { 109 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished); 110 mOnFinishedEvents.clear(); 111 } 112 113 private: 114 std::vector<OnFinishedEvent> mOnFinishedEvents; 115 }; 116 117 class FinishAndInvokeListener : public MessageHandler { 118 public: 119 explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) 120 : mAnimator(anim) { 121 mListener = anim->getOneShotListener(); 122 mRequestId = anim->getRequestId(); 123 } 124 125 virtual void handleMessage(const Message& message) { 126 if (mAnimator->getRequestId() == mRequestId) { 127 // Request Id has not changed, meaning there's no animation lifecyle change since the 128 // message is posted, so go ahead and call finish to make sure the PlayState is properly 129 // updated. This is needed because before the next frame comes in from UI thread to 130 // trigger an animation update, there could be reverse/cancel etc. So we need to update 131 // the playstate in time to ensure all the subsequent events get chained properly. 132 mAnimator->end(); 133 } 134 mListener->onAnimationFinished(nullptr); 135 } 136 private: 137 sp<PropertyValuesAnimatorSet> mAnimator; 138 sp<AnimationListener> mListener; 139 uint32_t mRequestId; 140 }; 141 142 class RenderingException : public MessageHandler { 143 public: 144 RenderingException(JavaVM* vm, const std::string& message) 145 : mVm(vm) 146 , mMessage(message) { 147 } 148 149 virtual void handleMessage(const Message&) { 150 throwException(mVm, mMessage); 151 } 152 153 static void throwException(JavaVM* vm, const std::string& message) { 154 JNIEnv* env = getenv(vm); 155 jniThrowException(env, "java/lang/IllegalStateException", message.c_str()); 156 } 157 158 private: 159 JavaVM* mVm; 160 std::string mMessage; 161 }; 162 163 class FrameCompleteWrapper : public MessageHandler { 164 public: 165 FrameCompleteWrapper(JNIEnv* env, jobject jobject) { 166 mLooper = Looper::getForThread(); 167 LOG_ALWAYS_FATAL_IF(!mLooper.get(), "Must create runnable on a Looper thread!"); 168 env->GetJavaVM(&mVm); 169 mObject = env->NewGlobalRef(jobject); 170 LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); 171 } 172 173 virtual ~FrameCompleteWrapper() { 174 releaseObject(); 175 } 176 177 void postFrameComplete(int64_t frameNr) { 178 if (mObject) { 179 mFrameNr = frameNr; 180 mLooper->sendMessage(this, 0); 181 } 182 } 183 184 virtual void handleMessage(const Message&) { 185 if (mObject) { 186 ATRACE_FORMAT("frameComplete %" PRId64, mFrameNr); 187 getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, mFrameNr); 188 releaseObject(); 189 } 190 } 191 192 private: 193 JavaVM* mVm; 194 jobject mObject; 195 sp<Looper> mLooper; 196 int64_t mFrameNr = -1; 197 198 void releaseObject() { 199 if (mObject) { 200 getenv(mVm)->DeleteGlobalRef(mObject); 201 mObject = nullptr; 202 } 203 } 204 }; 205 206 class RootRenderNode : public RenderNode, ErrorHandler { 207 public: 208 explicit RootRenderNode(JNIEnv* env) : RenderNode() { 209 mLooper = Looper::getForThread(); 210 LOG_ALWAYS_FATAL_IF(!mLooper.get(), 211 "Must create RootRenderNode on a thread with a looper!"); 212 env->GetJavaVM(&mVm); 213 } 214 215 virtual ~RootRenderNode() {} 216 217 virtual void onError(const std::string& message) override { 218 mLooper->sendMessage(new RenderingException(mVm, message), 0); 219 } 220 221 virtual void prepareTree(TreeInfo& info) override { 222 info.errorHandler = this; 223 224 for (auto& anim : mRunningVDAnimators) { 225 // Assume that the property change in VD from the animators will not be consumed. Mark 226 // otherwise if the VDs are found in the display list tree. For VDs that are not in 227 // the display list tree, we stop providing animation pulses by 1) removing them from 228 // the animation list, 2) post a delayed message to end them at end time so their 229 // listeners can receive the corresponding callbacks. 230 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); 231 // Mark the VD dirty so it will damage itself during prepareTree. 232 anim->getVectorDrawable()->markDirty(); 233 } 234 if (info.mode == TreeInfo::MODE_FULL) { 235 for (auto &anim : mPausedVDAnimators) { 236 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); 237 anim->getVectorDrawable()->markDirty(); 238 } 239 } 240 // TODO: This is hacky 241 info.updateWindowPositions = true; 242 RenderNode::prepareTree(info); 243 info.updateWindowPositions = false; 244 info.errorHandler = nullptr; 245 } 246 247 void sendMessage(const sp<MessageHandler>& handler) { 248 mLooper->sendMessage(handler, 0); 249 } 250 251 void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) { 252 mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0); 253 } 254 255 void attachAnimatingNode(RenderNode* animatingNode) { 256 mPendingAnimatingRenderNodes.push_back(animatingNode); 257 } 258 259 void attachPendingVectorDrawableAnimators() { 260 mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(), 261 mPendingVectorDrawableAnimators.end()); 262 mPendingVectorDrawableAnimators.clear(); 263 } 264 265 void detachAnimators() { 266 // Remove animators from the list and post a delayed message in future to end the animator 267 // For infinite animators, remove the listener so we no longer hold a global ref to the AVD 268 // java object, and therefore the AVD objects in both native and Java can be properly 269 // released. 270 for (auto& anim : mRunningVDAnimators) { 271 detachVectorDrawableAnimator(anim.get()); 272 anim->clearOneShotListener(); 273 } 274 for (auto& anim : mPausedVDAnimators) { 275 anim->clearOneShotListener(); 276 } 277 mRunningVDAnimators.clear(); 278 mPausedVDAnimators.clear(); 279 } 280 281 // Move all the animators to the paused list, and send a delayed message to notify the finished 282 // listener. 283 void pauseAnimators() { 284 mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end()); 285 for (auto& anim : mRunningVDAnimators) { 286 detachVectorDrawableAnimator(anim.get()); 287 } 288 mRunningVDAnimators.clear(); 289 } 290 291 void doAttachAnimatingNodes(AnimationContext* context) { 292 for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) { 293 RenderNode* node = mPendingAnimatingRenderNodes[i].get(); 294 context->addAnimatingRenderNode(*node); 295 } 296 mPendingAnimatingRenderNodes.clear(); 297 } 298 299 // Run VectorDrawable animators after prepareTree. 300 void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) { 301 // Push staging. 302 if (info.mode == TreeInfo::MODE_FULL) { 303 pushStagingVectorDrawableAnimators(context); 304 } 305 306 // Run the animators in the running list. 307 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { 308 if ((*it)->animate(*context)) { 309 it = mRunningVDAnimators.erase(it); 310 } else { 311 it++; 312 } 313 } 314 315 // Run the animators in paused list during full sync. 316 if (info.mode == TreeInfo::MODE_FULL) { 317 // During full sync we also need to pulse paused animators, in case their targets 318 // have been added back to the display list. All the animators that passed the 319 // scheduled finish time will be removed from the paused list. 320 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 321 if ((*it)->animate(*context)) { 322 // Animator has finished, remove from the list. 323 it = mPausedVDAnimators.erase(it); 324 } else { 325 it++; 326 } 327 } 328 } 329 330 // Move the animators with a target not in DisplayList to paused list. 331 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { 332 if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { 333 // Vector Drawable is not in the display list, we should remove this animator from 334 // the list, put it in the paused list, and post a delayed message to end the 335 // animator. 336 detachVectorDrawableAnimator(it->get()); 337 mPausedVDAnimators.insert(*it); 338 it = mRunningVDAnimators.erase(it); 339 } else { 340 it++; 341 } 342 } 343 344 // Move the animators with a target in DisplayList from paused list to running list, and 345 // trim paused list. 346 if (info.mode == TreeInfo::MODE_FULL) { 347 // Check whether any paused animator's target is back in Display List. If so, put the 348 // animator back in the running list. 349 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 350 if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { 351 mRunningVDAnimators.insert(*it); 352 it = mPausedVDAnimators.erase(it); 353 } else { 354 it++; 355 } 356 } 357 // Trim paused VD animators at full sync, so that when Java loses reference to an 358 // animator, we know we won't be requested to animate it any more, then we remove such 359 // animators from the paused list so they can be properly freed. We also remove the 360 // animators from paused list when the time elapsed since start has exceeded duration. 361 trimPausedVDAnimators(context); 362 } 363 364 info.out.hasAnimations |= !mRunningVDAnimators.empty(); 365 } 366 367 void trimPausedVDAnimators(AnimationContext* context) { 368 // Trim paused vector drawable animator list. 369 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 370 // Remove paused VD animator if no one else is referencing it. Note that animators that 371 // have passed scheduled finish time are removed from list when they are being pulsed 372 // before prepare tree. 373 // TODO: this is a bit hacky, need to figure out a better way to track when the paused 374 // animators should be freed. 375 if ((*it)->getStrongCount() == 1) { 376 it = mPausedVDAnimators.erase(it); 377 } else { 378 it++; 379 } 380 } 381 } 382 383 void pushStagingVectorDrawableAnimators(AnimationContext* context) { 384 for (auto& anim : mRunningVDAnimators) { 385 anim->pushStaging(*context); 386 } 387 } 388 389 void destroy() { 390 for (auto& renderNode : mPendingAnimatingRenderNodes) { 391 renderNode->animators().endAllStagingAnimators(); 392 } 393 mPendingAnimatingRenderNodes.clear(); 394 mPendingVectorDrawableAnimators.clear(); 395 } 396 397 void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { 398 mPendingVectorDrawableAnimators.insert(anim); 399 } 400 401 private: 402 sp<Looper> mLooper; 403 JavaVM* mVm; 404 std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes; 405 std::set< sp<PropertyValuesAnimatorSet> > mPendingVectorDrawableAnimators; 406 std::set< sp<PropertyValuesAnimatorSet> > mRunningVDAnimators; 407 // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but 408 // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when 409 // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators 410 // need to be re-activated once their VD target is added back into DisplayList. Since that could 411 // only happen when we do a full sync, we need to make sure to pulse these paused animators at 412 // full sync. If any animator's VD target is found in DisplayList during a full sync, we move 413 // the animator back to the running list. 414 std::set< sp<PropertyValuesAnimatorSet> > mPausedVDAnimators; 415 void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { 416 if (anim->isInfinite() || !anim->isRunning()) { 417 // Do not need to post anything if the animation is infinite (i.e. no meaningful 418 // end listener action), or if the animation has already ended. 419 return; 420 } 421 nsecs_t remainingTimeInMs = anim->getRemainingPlayTime(); 422 // Post a delayed onFinished event that is scheduled to be handled when the animator ends. 423 if (anim->getOneShotListener()) { 424 // VectorDrawable's oneshot listener is updated when there are user triggered animation 425 // lifecycle changes, such as start(), end(), etc. By using checking and clearing 426 // one shot listener, we ensure the same end listener event gets posted only once. 427 // Therefore no duplicates. Another benefit of using one shot listener is that no 428 // removal is necessary: the end time of animation will not change unless triggered by 429 // user events, in which case the already posted listener's id will become stale, and 430 // the onFinished callback will then be ignored. 431 sp<FinishAndInvokeListener> message 432 = new FinishAndInvokeListener(anim); 433 sendMessageDelayed(message, remainingTimeInMs); 434 anim->clearOneShotListener(); 435 } 436 } 437 }; 438 439 class AnimationContextBridge : public AnimationContext { 440 public: 441 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode) 442 : AnimationContext(clock), mRootNode(rootNode) { 443 } 444 445 virtual ~AnimationContextBridge() {} 446 447 // Marks the start of a frame, which will update the frame time and move all 448 // next frame animations into the current frame 449 virtual void startFrame(TreeInfo::TraversalMode mode) { 450 if (mode == TreeInfo::MODE_FULL) { 451 mRootNode->doAttachAnimatingNodes(this); 452 mRootNode->attachPendingVectorDrawableAnimators(); 453 } 454 AnimationContext::startFrame(mode); 455 } 456 457 // Runs any animations still left in mCurrentFrameAnimations 458 virtual void runRemainingAnimations(TreeInfo& info) { 459 AnimationContext::runRemainingAnimations(info); 460 mRootNode->runVectorDrawableAnimators(this, info); 461 postOnFinishedEvents(); 462 } 463 464 virtual void pauseAnimators() override { 465 mRootNode->pauseAnimators(); 466 } 467 468 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { 469 OnFinishedEvent event(animator, listener); 470 mOnFinishedEvents.push_back(event); 471 } 472 473 virtual void destroy() { 474 AnimationContext::destroy(); 475 mRootNode->detachAnimators(); 476 postOnFinishedEvents(); 477 } 478 479 private: 480 sp<RootRenderNode> mRootNode; 481 std::vector<OnFinishedEvent> mOnFinishedEvents; 482 483 void postOnFinishedEvents() { 484 if (mOnFinishedEvents.size()) { 485 sp<InvokeAnimationListeners> message 486 = new InvokeAnimationListeners(mOnFinishedEvents); 487 mRootNode->sendMessage(message); 488 } 489 } 490 }; 491 492 class ContextFactoryImpl : public IContextFactory { 493 public: 494 explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {} 495 496 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { 497 return new AnimationContextBridge(clock, mRootNode); 498 } 499 500 private: 501 RootRenderNode* mRootNode; 502 }; 503 504 class ObserverProxy; 505 506 class NotifyHandler : public MessageHandler { 507 public: 508 NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {} 509 510 virtual void handleMessage(const Message& message); 511 512 private: 513 JavaVM* const mVm; 514 ObserverProxy* const mObserver; 515 }; 516 517 static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) { 518 jobject frameMetrics = env->GetObjectField( 519 observer, gFrameMetricsObserverClassInfo.frameMetrics); 520 LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object"); 521 jobject buffer = env->GetObjectField( 522 frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer); 523 LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer"); 524 return reinterpret_cast<jlongArray>(buffer); 525 } 526 527 /* 528 * Implements JNI layer for hwui frame metrics reporting. 529 */ 530 class ObserverProxy : public FrameMetricsObserver { 531 public: 532 ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) { 533 JNIEnv* env = getenv(mVm); 534 535 mObserverWeak = env->NewWeakGlobalRef(observer); 536 LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr, 537 "unable to create frame stats observer reference"); 538 539 jlongArray buffer = get_metrics_buffer(env, observer); 540 jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer)); 541 LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize, 542 "Mismatched Java/Native FrameMetrics data format."); 543 544 jobject messageQueueLocal = env->GetObjectField( 545 observer, gFrameMetricsObserverClassInfo.messageQueue); 546 mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal); 547 LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available"); 548 549 mMessageHandler = new NotifyHandler(mVm, this); 550 LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr, 551 "OOM: unable to allocate NotifyHandler"); 552 } 553 554 ~ObserverProxy() { 555 JNIEnv* env = getenv(mVm); 556 env->DeleteWeakGlobalRef(mObserverWeak); 557 } 558 559 jweak getObserverReference() { 560 return mObserverWeak; 561 } 562 563 bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) { 564 FrameMetricsNotification& elem = mRingBuffer[mNextInQueue]; 565 566 if (elem.hasData.load()) { 567 env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer); 568 *dropCount = elem.dropCount; 569 mNextInQueue = (mNextInQueue + 1) % kRingSize; 570 elem.hasData = false; 571 return true; 572 } 573 574 return false; 575 } 576 577 virtual void notify(const int64_t* stats) { 578 FrameMetricsNotification& elem = mRingBuffer[mNextFree]; 579 580 if (!elem.hasData.load()) { 581 memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0])); 582 583 elem.dropCount = mDroppedReports; 584 mDroppedReports = 0; 585 586 incStrong(nullptr); 587 mNextFree = (mNextFree + 1) % kRingSize; 588 elem.hasData = true; 589 590 mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage); 591 } else { 592 mDroppedReports++; 593 } 594 } 595 596 private: 597 static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes); 598 static constexpr int kRingSize = 3; 599 600 class FrameMetricsNotification { 601 public: 602 FrameMetricsNotification() : hasData(false) {} 603 604 std::atomic_bool hasData; 605 int64_t buffer[kBufferSize]; 606 int dropCount = 0; 607 }; 608 609 JavaVM* const mVm; 610 jweak mObserverWeak; 611 612 sp<MessageQueue> mMessageQueue; 613 sp<NotifyHandler> mMessageHandler; 614 Message mMessage; 615 616 int mNextFree = 0; 617 int mNextInQueue = 0; 618 FrameMetricsNotification mRingBuffer[kRingSize]; 619 620 int mDroppedReports = 0; 621 }; 622 623 void NotifyHandler::handleMessage(const Message& message) { 624 JNIEnv* env = getenv(mVm); 625 626 jobject target = env->NewLocalRef(mObserver->getObserverReference()); 627 628 if (target != nullptr) { 629 jlongArray javaBuffer = get_metrics_buffer(env, target); 630 int dropCount = 0; 631 while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) { 632 env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount); 633 } 634 env->DeleteLocalRef(target); 635 } 636 637 mObserver->decStrong(nullptr); 638 } 639 640 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) { 641 RenderProxy::rotateProcessStatsBuffer(); 642 } 643 644 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz, 645 jint fd) { 646 RenderProxy::setProcessStatsBuffer(fd); 647 } 648 649 static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz, 650 jlong proxyPtr) { 651 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 652 return proxy->getRenderThreadTid(); 653 } 654 655 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { 656 RootRenderNode* node = new RootRenderNode(env); 657 node->incStrong(0); 658 node->setName("RootRenderNode"); 659 return reinterpret_cast<jlong>(node); 660 } 661 662 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, 663 jboolean translucent, jlong rootRenderNodePtr) { 664 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr); 665 ContextFactoryImpl factory(rootRenderNode); 666 return (jlong) new RenderProxy(translucent, rootRenderNode, &factory); 667 } 668 669 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, 670 jlong proxyPtr) { 671 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 672 delete proxy; 673 } 674 675 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz, 676 jlong proxyPtr) { 677 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 678 return proxy->loadSystemProperties(); 679 } 680 681 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz, 682 jlong proxyPtr, jstring jname) { 683 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 684 const char* name = env->GetStringUTFChars(jname, NULL); 685 proxy->setName(name); 686 env->ReleaseStringUTFChars(jname, name); 687 } 688 689 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz, 690 jlong proxyPtr, jobject jsurface) { 691 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 692 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 693 proxy->initialize(surface); 694 } 695 696 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz, 697 jlong proxyPtr, jobject jsurface) { 698 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 699 sp<Surface> surface; 700 if (jsurface) { 701 surface = android_view_Surface_getSurface(env, jsurface); 702 } 703 proxy->updateSurface(surface); 704 } 705 706 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz, 707 jlong proxyPtr, jobject jsurface) { 708 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 709 sp<Surface> surface; 710 if (jsurface) { 711 surface = android_view_Surface_getSurface(env, jsurface); 712 } 713 return proxy->pauseSurface(surface); 714 } 715 716 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz, 717 jlong proxyPtr, jboolean stopped) { 718 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 719 proxy->setStopped(stopped); 720 } 721 722 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr, 723 jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) { 724 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 725 proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); 726 } 727 728 static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz, 729 jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) { 730 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 731 proxy->setLightCenter((Vector3){lightX, lightY, lightZ}); 732 } 733 734 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, 735 jlong proxyPtr, jboolean opaque) { 736 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 737 proxy->setOpaque(opaque); 738 } 739 740 static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz, 741 jlong proxyPtr, jboolean wideGamut) { 742 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 743 proxy->setWideGamut(wideGamut); 744 } 745 746 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, 747 jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) { 748 LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE, 749 "Mismatched size expectations, given %d expected %d", 750 frameInfoSize, UI_THREAD_FRAME_INFO_SIZE); 751 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 752 env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo()); 753 return proxy->syncAndDrawFrame(); 754 } 755 756 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz, 757 jlong proxyPtr, jlong rootNodePtr) { 758 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 759 rootRenderNode->destroy(); 760 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 761 proxy->destroy(); 762 } 763 764 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz, 765 jlong rootNodePtr, jlong animatingNodePtr) { 766 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 767 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr); 768 rootRenderNode->attachAnimatingNode(animatingNode); 769 } 770 771 static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz, 772 jlong rootNodePtr, jlong animatorPtr) { 773 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 774 PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr); 775 rootRenderNode->addVectorDrawableAnimator(animator); 776 } 777 778 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, 779 jlong functorPtr, jboolean waitForCompletion) { 780 Functor* functor = reinterpret_cast<Functor*>(functorPtr); 781 RenderProxy::invokeFunctor(functor, waitForCompletion); 782 } 783 784 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz, 785 jlong proxyPtr) { 786 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 787 DeferredLayerUpdater* layer = proxy->createTextureLayer(); 788 return reinterpret_cast<jlong>(layer); 789 } 790 791 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, 792 jlong proxyPtr, jlong nodePtr) { 793 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 794 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr); 795 proxy->buildLayer(node); 796 } 797 798 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, 799 jlong proxyPtr, jlong layerPtr, jobject jbitmap) { 800 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 801 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 802 SkBitmap bitmap; 803 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 804 return proxy->copyLayerInto(layer, bitmap); 805 } 806 807 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz, 808 jlong proxyPtr, jlong layerPtr) { 809 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 810 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 811 proxy->pushLayerUpdate(layer); 812 } 813 814 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz, 815 jlong proxyPtr, jlong layerPtr) { 816 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 817 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 818 proxy->cancelLayerUpdate(layer); 819 } 820 821 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz, 822 jlong proxyPtr, jlong layerPtr) { 823 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 824 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 825 proxy->detachSurfaceTexture(layer); 826 } 827 828 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz, 829 jlong proxyPtr) { 830 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 831 proxy->destroyHardwareResources(); 832 } 833 834 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz, 835 jint level) { 836 RenderProxy::trimMemory(level); 837 } 838 839 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz, 840 jstring name, jstring value) { 841 const char* nameCharArray = env->GetStringUTFChars(name, NULL); 842 const char* valueCharArray = env->GetStringUTFChars(value, NULL); 843 RenderProxy::overrideProperty(nameCharArray, valueCharArray); 844 env->ReleaseStringUTFChars(name, nameCharArray); 845 env->ReleaseStringUTFChars(name, valueCharArray); 846 } 847 848 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz, 849 jlong proxyPtr) { 850 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 851 proxy->fence(); 852 } 853 854 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz, 855 jlong proxyPtr) { 856 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 857 proxy->stopDrawing(); 858 } 859 860 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz, 861 jlong proxyPtr) { 862 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 863 proxy->notifyFramePending(); 864 } 865 866 static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz, 867 jlong proxyPtr) { 868 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 869 proxy->serializeDisplayListTree(); 870 } 871 872 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz, 873 jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) { 874 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 875 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); 876 proxy->dumpProfileInfo(fd, dumpFlags); 877 } 878 879 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz, 880 jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) { 881 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 882 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 883 proxy->addRenderNode(renderNode, placeFront); 884 } 885 886 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz, 887 jlong proxyPtr, jlong renderNodePtr) { 888 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 889 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 890 proxy->removeRenderNode(renderNode); 891 } 892 893 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz, 894 jlong proxyPtr, jlong renderNodePtr) { 895 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 896 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 897 proxy->drawRenderNode(renderNode); 898 } 899 900 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env, 901 jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) { 902 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 903 proxy->setContentDrawBounds(left, top, right, bottom); 904 } 905 906 class JGlobalRefHolder { 907 public: 908 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {} 909 910 virtual ~JGlobalRefHolder() { 911 getenv(mVm)->DeleteGlobalRef(mObject); 912 mObject = nullptr; 913 } 914 915 jobject object() { return mObject; } 916 JavaVM* vm() { return mVm; } 917 918 private: 919 JGlobalRefHolder(const JGlobalRefHolder&) = delete; 920 void operator=(const JGlobalRefHolder&) = delete; 921 922 JavaVM* mVm; 923 jobject mObject; 924 }; 925 926 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, 927 jobject clazz, jlong proxyPtr, jobject frameCallback) { 928 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 929 if (!frameCallback) { 930 proxy->setFrameCallback(nullptr); 931 } else { 932 JavaVM* vm = nullptr; 933 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); 934 auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm, 935 env->NewGlobalRef(frameCallback)); 936 proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) { 937 JNIEnv* env = getenv(globalCallbackRef->vm()); 938 env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw, 939 static_cast<jlong>(frameNr)); 940 }); 941 } 942 } 943 944 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, 945 jobject clazz, jlong proxyPtr, jobject callback) { 946 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 947 if (!callback) { 948 proxy->setFrameCompleteCallback(nullptr); 949 } else { 950 sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; 951 proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { 952 wrapper->postFrameComplete(frameNr); 953 }); 954 } 955 } 956 957 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, 958 jobject clazz, jobject jsurface, jint left, jint top, 959 jint right, jint bottom, jobject jbitmap) { 960 SkBitmap bitmap; 961 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 962 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 963 return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap); 964 } 965 966 class ContextFactory : public IContextFactory { 967 public: 968 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { 969 return new AnimationContext(clock); 970 } 971 }; 972 973 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env, 974 jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) { 975 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 976 if (jwidth <= 0 || jheight <= 0) { 977 ALOGW("Invalid width %d or height %d", jwidth, jheight); 978 return nullptr; 979 } 980 981 uint32_t width = jwidth; 982 uint32_t height = jheight; 983 984 // Create a Surface wired up to a BufferItemConsumer 985 sp<IGraphicBufferProducer> producer; 986 sp<IGraphicBufferConsumer> rawConsumer; 987 BufferQueue::createBufferQueue(&producer, &rawConsumer); 988 // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2 989 rawConsumer->setMaxBufferCount(2); 990 sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer, 991 GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER); 992 consumer->setDefaultBufferSize(width, height); 993 sp<Surface> surface = new Surface(producer); 994 995 // Render into the surface 996 { 997 ContextFactory factory; 998 RenderProxy proxy{true, renderNode, &factory}; 999 proxy.loadSystemProperties(); 1000 proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer); 1001 proxy.initialize(surface); 1002 // Shadows can't be used via this interface, so just set the light source 1003 // to all 0s. 1004 proxy.setup(0, 0, 0); 1005 proxy.setLightCenter((Vector3){0, 0, 0}); 1006 nsecs_t vsync = systemTime(CLOCK_MONOTONIC); 1007 UiFrameInfoBuilder(proxy.frameInfo()) 1008 .setVsync(vsync, vsync) 1009 .addFlag(FrameInfoFlags::SurfaceCanvas); 1010 proxy.syncAndDrawFrame(); 1011 } 1012 1013 // Yank out the GraphicBuffer 1014 BufferItem bufferItem; 1015 status_t err; 1016 if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) { 1017 ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err)); 1018 return nullptr; 1019 } 1020 sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer; 1021 // We don't really care if this fails or not since we're just going to destroy this anyway 1022 consumer->releaseBuffer(bufferItem); 1023 if (!buffer.get()) { 1024 ALOGW("GraphicBuffer is null?"); 1025 return nullptr; 1026 } 1027 if (buffer->getWidth() != width || buffer->getHeight() != height) { 1028 ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d", 1029 buffer->getWidth(), buffer->getHeight(), width, height); 1030 // Continue I guess? 1031 } 1032 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer); 1033 return bitmap::createBitmap(env, bitmap.release(), 1034 android::bitmap::kBitmapCreateFlag_Premultiplied); 1035 } 1036 1037 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) { 1038 RenderProxy::disableVsync(); 1039 } 1040 1041 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) { 1042 Properties::enableHighContrastText = enable; 1043 } 1044 1045 static void android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv*, jclass, 1046 jboolean enable) { 1047 Properties::enableRTAnimations = enable; 1048 } 1049 1050 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) { 1051 Properties::debuggingEnabled = enable; 1052 } 1053 1054 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) { 1055 Properties::isolatedProcess = isolated; 1056 } 1057 1058 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass, 1059 jint contextPriority) { 1060 Properties::contextPriority = contextPriority; 1061 } 1062 1063 // ---------------------------------------------------------------------------- 1064 // FrameMetricsObserver 1065 // ---------------------------------------------------------------------------- 1066 1067 static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env, 1068 jclass clazz, jlong proxyPtr, jobject fso) { 1069 JavaVM* vm = nullptr; 1070 if (env->GetJavaVM(&vm) != JNI_OK) { 1071 LOG_ALWAYS_FATAL("Unable to get Java VM"); 1072 return 0; 1073 } 1074 1075 renderthread::RenderProxy* renderProxy = 1076 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 1077 1078 FrameMetricsObserver* observer = new ObserverProxy(vm, fso); 1079 renderProxy->addFrameMetricsObserver(observer); 1080 return reinterpret_cast<jlong>(observer); 1081 } 1082 1083 static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz, 1084 jlong proxyPtr, jlong observerPtr) { 1085 FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr); 1086 renderthread::RenderProxy* renderProxy = 1087 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 1088 1089 renderProxy->removeFrameMetricsObserver(observer); 1090 } 1091 1092 // ---------------------------------------------------------------------------- 1093 // Shaders 1094 // ---------------------------------------------------------------------------- 1095 1096 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, 1097 jstring diskCachePath, jstring skiaDiskCachePath) { 1098 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); 1099 android::egl_set_cache_filename(cacheArray); 1100 env->ReleaseStringUTFChars(diskCachePath, cacheArray); 1101 1102 const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL); 1103 uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray); 1104 env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray); 1105 } 1106 1107 // ---------------------------------------------------------------------------- 1108 // JNI Glue 1109 // ---------------------------------------------------------------------------- 1110 1111 const char* const kClassPathName = "android/view/ThreadedRenderer"; 1112 1113 static const JNINativeMethod gMethods[] = { 1114 { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer }, 1115 { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer }, 1116 { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid }, 1117 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, 1118 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, 1119 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, 1120 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, 1121 { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName }, 1122 { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize }, 1123 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, 1124 { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface }, 1125 { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped }, 1126 { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup }, 1127 { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, 1128 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, 1129 { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut }, 1130 { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, 1131 { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, 1132 { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, 1133 { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator }, 1134 { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, 1135 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, 1136 { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, 1137 { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, 1138 { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, 1139 { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, 1140 { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture }, 1141 { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources }, 1142 { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory }, 1143 { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) android_view_ThreadedRenderer_overrideProperty }, 1144 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence }, 1145 { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing }, 1146 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending }, 1147 { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree }, 1148 { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo }, 1149 { "setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V", 1150 (void*) android_view_ThreadedRenderer_setupShadersDiskCache }, 1151 { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode}, 1152 { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode}, 1153 { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode}, 1154 { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds}, 1155 { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V", 1156 (void*)android_view_ThreadedRenderer_setFrameCallback}, 1157 { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V", 1158 (void*)android_view_ThreadedRenderer_setFrameCompleteCallback }, 1159 { "nAddFrameMetricsObserver", 1160 "(JLandroid/view/FrameMetricsObserver;)J", 1161 (void*)android_view_ThreadedRenderer_addFrameMetricsObserver }, 1162 { "nRemoveFrameMetricsObserver", 1163 "(JJ)V", 1164 (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver }, 1165 { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I", 1166 (void*)android_view_ThreadedRenderer_copySurfaceInto }, 1167 { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;", 1168 (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode }, 1169 { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync }, 1170 { "nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText }, 1171 { "nHackySetRTAnimationsEnabled", "(Z)V", 1172 (void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled }, 1173 { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled }, 1174 { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess }, 1175 { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority }, 1176 }; 1177 1178 static JavaVM* mJvm = nullptr; 1179 1180 static void attachRenderThreadToJvm() { 1181 LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??"); 1182 1183 JavaVMAttachArgs args; 1184 args.version = JNI_VERSION_1_4; 1185 args.name = (char*) "RenderThread"; 1186 args.group = NULL; 1187 JNIEnv* env; 1188 mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args); 1189 } 1190 1191 int register_android_view_ThreadedRenderer(JNIEnv* env) { 1192 env->GetJavaVM(&mJvm); 1193 RenderThread::setOnStartHook(&attachRenderThreadToJvm); 1194 jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver"); 1195 gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie( 1196 env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;"); 1197 gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie( 1198 env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;"); 1199 gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie( 1200 env, observerClass, "notifyDataAvailable", "(I)V"); 1201 1202 jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics"); 1203 gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie( 1204 env, metricsClass, "mTimingData", "[J"); 1205 1206 jclass frameCallbackClass = FindClassOrDie(env, 1207 "android/view/ThreadedRenderer$FrameDrawingCallback"); 1208 gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, 1209 "onFrameDraw", "(J)V"); 1210 1211 jclass frameCompleteClass = FindClassOrDie(env, 1212 "android/view/ThreadedRenderer$FrameCompleteCallback"); 1213 gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, 1214 "onFrameComplete", "(J)V"); 1215 1216 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 1217 } 1218 1219 }; // namespace android 1220