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