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
getenv(JavaVM * vm)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:
OnFinishedEvent(BaseRenderNodeAnimator * animator,AnimationListener * listener)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:
InvokeAnimationListeners(std::vector<OnFinishedEvent> & events)100 explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
101 mOnFinishedEvents.swap(events);
102 }
103
callOnFinished(OnFinishedEvent & event)104 static void callOnFinished(OnFinishedEvent& event) {
105 event.listener->onAnimationFinished(event.animator.get());
106 }
107
handleMessage(const Message & message)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:
FinishAndInvokeListener(PropertyValuesAnimatorSet * anim)119 explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim)
120 : mAnimator(anim) {
121 mListener = anim->getOneShotListener();
122 mRequestId = anim->getRequestId();
123 }
124
handleMessage(const Message & message)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:
RenderingException(JavaVM * vm,const std::string & message)144 RenderingException(JavaVM* vm, const std::string& message)
145 : mVm(vm)
146 , mMessage(message) {
147 }
148
handleMessage(const Message &)149 virtual void handleMessage(const Message&) {
150 throwException(mVm, mMessage);
151 }
152
throwException(JavaVM * vm,const std::string & message)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:
FrameCompleteWrapper(JNIEnv * env,jobject jobject)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
~FrameCompleteWrapper()173 virtual ~FrameCompleteWrapper() {
174 releaseObject();
175 }
176
postFrameComplete(int64_t frameNr)177 void postFrameComplete(int64_t frameNr) {
178 if (mObject) {
179 mFrameNr = frameNr;
180 mLooper->sendMessage(this, 0);
181 }
182 }
183
handleMessage(const Message &)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
releaseObject()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:
RootRenderNode(JNIEnv * env)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
~RootRenderNode()215 virtual ~RootRenderNode() {}
216
onError(const std::string & message)217 virtual void onError(const std::string& message) override {
218 mLooper->sendMessage(new RenderingException(mVm, message), 0);
219 }
220
prepareTree(TreeInfo & info)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
sendMessage(const sp<MessageHandler> & handler)247 void sendMessage(const sp<MessageHandler>& handler) {
248 mLooper->sendMessage(handler, 0);
249 }
250
sendMessageDelayed(const sp<MessageHandler> & handler,nsecs_t delayInMs)251 void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) {
252 mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0);
253 }
254
attachAnimatingNode(RenderNode * animatingNode)255 void attachAnimatingNode(RenderNode* animatingNode) {
256 mPendingAnimatingRenderNodes.push_back(animatingNode);
257 }
258
attachPendingVectorDrawableAnimators()259 void attachPendingVectorDrawableAnimators() {
260 mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(),
261 mPendingVectorDrawableAnimators.end());
262 mPendingVectorDrawableAnimators.clear();
263 }
264
detachAnimators()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.
pauseAnimators()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
doAttachAnimatingNodes(AnimationContext * context)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.
runVectorDrawableAnimators(AnimationContext * context,TreeInfo & info)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
trimPausedVDAnimators(AnimationContext * context)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
pushStagingVectorDrawableAnimators(AnimationContext * context)383 void pushStagingVectorDrawableAnimators(AnimationContext* context) {
384 for (auto& anim : mRunningVDAnimators) {
385 anim->pushStaging(*context);
386 }
387 }
388
destroy()389 void destroy() {
390 for (auto& renderNode : mPendingAnimatingRenderNodes) {
391 renderNode->animators().endAllStagingAnimators();
392 }
393 mPendingAnimatingRenderNodes.clear();
394 mPendingVectorDrawableAnimators.clear();
395 }
396
addVectorDrawableAnimator(PropertyValuesAnimatorSet * anim)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;
detachVectorDrawableAnimator(PropertyValuesAnimatorSet * anim)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:
AnimationContextBridge(renderthread::TimeLord & clock,RootRenderNode * rootNode)441 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
442 : AnimationContext(clock), mRootNode(rootNode) {
443 }
444
~AnimationContextBridge()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
startFrame(TreeInfo::TraversalMode mode)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
runRemainingAnimations(TreeInfo & info)458 virtual void runRemainingAnimations(TreeInfo& info) {
459 AnimationContext::runRemainingAnimations(info);
460 mRootNode->runVectorDrawableAnimators(this, info);
461 postOnFinishedEvents();
462 }
463
pauseAnimators()464 virtual void pauseAnimators() override {
465 mRootNode->pauseAnimators();
466 }
467
callOnFinished(BaseRenderNodeAnimator * animator,AnimationListener * listener)468 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
469 OnFinishedEvent event(animator, listener);
470 mOnFinishedEvents.push_back(event);
471 }
472
destroy()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
postOnFinishedEvents()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:
ContextFactoryImpl(RootRenderNode * rootNode)494 explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
495
createAnimationContext(renderthread::TimeLord & clock)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:
NotifyHandler(JavaVM * vm,ObserverProxy * observer)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
get_metrics_buffer(JNIEnv * env,jobject observer)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:
ObserverProxy(JavaVM * vm,jobject observer)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
~ObserverProxy()554 ~ObserverProxy() {
555 JNIEnv* env = getenv(mVm);
556 env->DeleteWeakGlobalRef(mObserverWeak);
557 }
558
getObserverReference()559 jweak getObserverReference() {
560 return mObserverWeak;
561 }
562
getNextBuffer(JNIEnv * env,jlongArray sink,int * dropCount)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
notify(const int64_t * stats)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:
FrameMetricsNotification()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
handleMessage(const Message & message)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
android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv * env,jobject clazz)640 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
641 RenderProxy::rotateProcessStatsBuffer();
642 }
643
android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv * env,jobject clazz,jint fd)644 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
645 jint fd) {
646 RenderProxy::setProcessStatsBuffer(fd);
647 }
648
android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_createRootRenderNode(JNIEnv * env,jobject clazz)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
android_view_ThreadedRenderer_createProxy(JNIEnv * env,jobject clazz,jboolean translucent,jlong rootRenderNodePtr)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
android_view_ThreadedRenderer_deleteProxy(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_loadSystemProperties(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_setName(JNIEnv * env,jobject clazz,jlong proxyPtr,jstring jname)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
android_view_ThreadedRenderer_initialize(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)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
android_view_ThreadedRenderer_updateSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)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
android_view_ThreadedRenderer_pauseSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)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
android_view_ThreadedRenderer_setStopped(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean stopped)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
android_view_ThreadedRenderer_setup(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat lightRadius,jint ambientShadowAlpha,jint spotShadowAlpha)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
android_view_ThreadedRenderer_setLightCenter(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat lightX,jfloat lightY,jfloat lightZ)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
android_view_ThreadedRenderer_setOpaque(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean opaque)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
android_view_ThreadedRenderer_setWideGamut(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean wideGamut)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
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlongArray frameInfo,jint frameInfoSize)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
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong rootNodePtr)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
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)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
android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatorPtr)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
android_view_ThreadedRenderer_invokeFunctor(JNIEnv * env,jobject clazz,jlong functorPtr,jboolean waitForCompletion)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
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)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
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jobject jbitmap)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
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)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
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)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
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)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
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)834 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
835 jint level) {
836 RenderProxy::trimMemory(level);
837 }
838
android_view_ThreadedRenderer_overrideProperty(JNIEnv * env,jobject clazz,jstring name,jstring value)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
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv * env,jobject clazz,jlong proxyPtr)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
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor,jint dumpFlags)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
android_view_ThreadedRenderer_addRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr,jboolean placeFront)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
android_view_ThreadedRenderer_removeRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)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
android_view_ThreadedRendererd_drawRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)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
android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv * env,jobject clazz,jlong proxyPtr,jint left,jint top,jint right,jint bottom)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:
JGlobalRefHolder(JavaVM * vm,jobject object)908 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
909
~JGlobalRefHolder()910 virtual ~JGlobalRefHolder() {
911 getenv(mVm)->DeleteGlobalRef(mObject);
912 mObject = nullptr;
913 }
914
object()915 jobject object() { return mObject; }
vm()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
android_view_ThreadedRenderer_setFrameCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject frameCallback)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
android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)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
android_view_ThreadedRenderer_copySurfaceInto(JNIEnv * env,jobject clazz,jobject jsurface,jint left,jint top,jint right,jint bottom,jobject jbitmap)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:
createAnimationContext(renderthread::TimeLord & clock)968 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
969 return new AnimationContext(clock);
970 }
971 };
972
android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv * env,jobject clazz,jlong renderNodePtr,jint jwidth,jint jheight)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
android_view_ThreadedRenderer_disableVsync(JNIEnv *,jclass)1037 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
1038 RenderProxy::disableVsync();
1039 }
1040
android_view_ThreadedRenderer_setHighContrastText(JNIEnv *,jclass,jboolean enable)1041 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
1042 Properties::enableHighContrastText = enable;
1043 }
1044
android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv *,jclass,jboolean enable)1045 static void android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv*, jclass,
1046 jboolean enable) {
1047 Properties::enableRTAnimations = enable;
1048 }
1049
android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv *,jclass,jboolean enable)1050 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
1051 Properties::debuggingEnabled = enable;
1052 }
1053
android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv *,jclass,jboolean isolated)1054 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
1055 Properties::isolatedProcess = isolated;
1056 }
1057
android_view_ThreadedRenderer_setContextPriority(JNIEnv *,jclass,jint contextPriority)1058 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
1059 jint contextPriority) {
1060 Properties::contextPriority = contextPriority;
1061 }
1062
1063 // ----------------------------------------------------------------------------
1064 // FrameMetricsObserver
1065 // ----------------------------------------------------------------------------
1066
android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jobject fso)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
android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)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
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath,jstring skiaDiskCachePath)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
attachRenderThreadToJvm()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
register_android_view_ThreadedRenderer(JNIEnv * env)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