1 /*
2 * Copyright 2016 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 #include <gui/FrameTimestamps.h>
18
19 #define LOG_TAG "FrameEvents"
20
21 #include <cutils/compiler.h> // For CC_[UN]LIKELY
22 #include <inttypes.h>
23 #include <utils/Log.h>
24 #include <utils/String8.h>
25
26 #include <algorithm>
27 #include <limits>
28 #include <numeric>
29
30 namespace android {
31
32
33 // ============================================================================
34 // FrameEvents
35 // ============================================================================
36
hasPostedInfo() const37 bool FrameEvents::hasPostedInfo() const {
38 return FrameEvents::isValidTimestamp(postedTime);
39 }
40
hasRequestedPresentInfo() const41 bool FrameEvents::hasRequestedPresentInfo() const {
42 return FrameEvents::isValidTimestamp(requestedPresentTime);
43 }
44
hasLatchInfo() const45 bool FrameEvents::hasLatchInfo() const {
46 return FrameEvents::isValidTimestamp(latchTime);
47 }
48
hasFirstRefreshStartInfo() const49 bool FrameEvents::hasFirstRefreshStartInfo() const {
50 return FrameEvents::isValidTimestamp(firstRefreshStartTime);
51 }
52
hasLastRefreshStartInfo() const53 bool FrameEvents::hasLastRefreshStartInfo() const {
54 // The last refresh start time may continue to update until a new frame
55 // is latched. We know we have the final value once the release info is set.
56 return addReleaseCalled;
57 }
58
hasDequeueReadyInfo() const59 bool FrameEvents::hasDequeueReadyInfo() const {
60 return FrameEvents::isValidTimestamp(dequeueReadyTime);
61 }
62
hasAcquireInfo() const63 bool FrameEvents::hasAcquireInfo() const {
64 return acquireFence->isValid();
65 }
66
hasGpuCompositionDoneInfo() const67 bool FrameEvents::hasGpuCompositionDoneInfo() const {
68 // We may not get a gpuCompositionDone in addPostComposite if
69 // client/gles compositing isn't needed.
70 return addPostCompositeCalled;
71 }
72
hasDisplayPresentInfo() const73 bool FrameEvents::hasDisplayPresentInfo() const {
74 // We may not get a displayPresent in addPostComposite for HWC1.
75 return addPostCompositeCalled;
76 }
77
hasReleaseInfo() const78 bool FrameEvents::hasReleaseInfo() const {
79 return addReleaseCalled;
80 }
81
checkFencesForCompletion()82 void FrameEvents::checkFencesForCompletion() {
83 acquireFence->getSignalTime();
84 gpuCompositionDoneFence->getSignalTime();
85 displayPresentFence->getSignalTime();
86 releaseFence->getSignalTime();
87 }
88
dumpFenceTime(String8 & outString,const char * name,bool pending,const FenceTime & fenceTime)89 static void dumpFenceTime(String8& outString, const char* name,
90 bool pending, const FenceTime& fenceTime) {
91 outString.appendFormat("--- %s", name);
92 nsecs_t signalTime = fenceTime.getCachedSignalTime();
93 if (Fence::isValidTimestamp(signalTime)) {
94 outString.appendFormat("%" PRId64 "\n", signalTime);
95 } else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) {
96 outString.appendFormat("Pending\n");
97 } else if (&fenceTime == FenceTime::NO_FENCE.get()){
98 outString.appendFormat("N/A\n");
99 } else {
100 outString.appendFormat("Error\n");
101 }
102 }
103
dump(String8 & outString) const104 void FrameEvents::dump(String8& outString) const
105 {
106 if (!valid) {
107 return;
108 }
109
110 outString.appendFormat("-- Frame %" PRIu64 "\n", frameNumber);
111 outString.appendFormat("--- Posted \t%" PRId64 "\n", postedTime);
112 outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
113
114 outString.appendFormat("--- Latched \t");
115 if (FrameEvents::isValidTimestamp(latchTime)) {
116 outString.appendFormat("%" PRId64 "\n", latchTime);
117 } else {
118 outString.appendFormat("Pending\n");
119 }
120
121 outString.appendFormat("--- Refresh (First)\t");
122 if (FrameEvents::isValidTimestamp(firstRefreshStartTime)) {
123 outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime);
124 } else {
125 outString.appendFormat("Pending\n");
126 }
127
128 outString.appendFormat("--- Refresh (Last)\t");
129 if (FrameEvents::isValidTimestamp(lastRefreshStartTime)) {
130 outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime);
131 } else {
132 outString.appendFormat("Pending\n");
133 }
134
135 dumpFenceTime(outString, "Acquire \t",
136 true, *acquireFence);
137 dumpFenceTime(outString, "GPU Composite Done\t",
138 !addPostCompositeCalled, *gpuCompositionDoneFence);
139 dumpFenceTime(outString, "Display Present \t",
140 !addPostCompositeCalled, *displayPresentFence);
141
142 outString.appendFormat("--- DequeueReady \t");
143 if (FrameEvents::isValidTimestamp(dequeueReadyTime)) {
144 outString.appendFormat("%" PRId64 "\n", dequeueReadyTime);
145 } else {
146 outString.appendFormat("Pending\n");
147 }
148
149 dumpFenceTime(outString, "Release \t",
150 true, *releaseFence);
151 }
152
153
154 // ============================================================================
155 // FrameEventHistory
156 // ============================================================================
157
158 namespace {
159
160 struct FrameNumberEqual {
FrameNumberEqualandroid::__anon8a3d95140111::FrameNumberEqual161 FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
operator ()android::__anon8a3d95140111::FrameNumberEqual162 bool operator()(const FrameEvents& frame) {
163 return frame.valid && mFrameNumber == frame.frameNumber;
164 }
165 const uint64_t mFrameNumber;
166 };
167
168 } // namespace
169
170 FrameEventHistory::~FrameEventHistory() = default;
171
getFrame(uint64_t frameNumber)172 FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) {
173 auto frame = std::find_if(
174 mFrames.begin(), mFrames.end(), FrameNumberEqual(frameNumber));
175 return frame == mFrames.end() ? nullptr : &(*frame);
176 }
177
getFrame(uint64_t frameNumber,size_t * iHint)178 FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber, size_t* iHint) {
179 *iHint = std::min(*iHint, mFrames.size());
180 auto hint = mFrames.begin() + *iHint;
181 auto frame = std::find_if(
182 hint, mFrames.end(), FrameNumberEqual(frameNumber));
183 if (frame == mFrames.end()) {
184 frame = std::find_if(
185 mFrames.begin(), hint, FrameNumberEqual(frameNumber));
186 if (frame == hint) {
187 return nullptr;
188 }
189 }
190 *iHint = static_cast<size_t>(std::distance(mFrames.begin(), frame));
191 return &(*frame);
192 }
193
checkFencesForCompletion()194 void FrameEventHistory::checkFencesForCompletion() {
195 for (auto& frame : mFrames) {
196 frame.checkFencesForCompletion();
197 }
198 }
199
200 // Uses !|valid| as the MSB.
FrameNumberLessThan(const FrameEvents & lhs,const FrameEvents & rhs)201 static bool FrameNumberLessThan(
202 const FrameEvents& lhs, const FrameEvents& rhs) {
203 if (lhs.valid == rhs.valid) {
204 return lhs.frameNumber < rhs.frameNumber;
205 }
206 return lhs.valid;
207 }
208
dump(String8 & outString) const209 void FrameEventHistory::dump(String8& outString) const {
210 auto earliestFrame = std::min_element(
211 mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
212 if (!earliestFrame->valid) {
213 outString.appendFormat("-- N/A\n");
214 return;
215 }
216 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
217 frame->dump(outString);
218 }
219 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
220 frame->dump(outString);
221 }
222 }
223
224
225 // ============================================================================
226 // ProducerFrameEventHistory
227 // ============================================================================
228
229 ProducerFrameEventHistory::~ProducerFrameEventHistory() = default;
230
snapToNextTick(nsecs_t timestamp,nsecs_t tickPhase,nsecs_t tickInterval)231 nsecs_t ProducerFrameEventHistory::snapToNextTick(
232 nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval) {
233 nsecs_t tickOffset = (tickPhase - timestamp) % tickInterval;
234 // Integer modulo rounds towards 0 and not -inf before taking the remainder,
235 // so adjust the offset if it is negative.
236 if (tickOffset < 0) {
237 tickOffset += tickInterval;
238 }
239 return timestamp + tickOffset;
240 }
241
getNextCompositeDeadline(const nsecs_t now) const242 nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline(
243 const nsecs_t now) const{
244 return snapToNextTick(
245 now, mCompositorTiming.deadline, mCompositorTiming.interval);
246 }
247
updateAcquireFence(uint64_t frameNumber,std::shared_ptr<FenceTime> && acquire)248 void ProducerFrameEventHistory::updateAcquireFence(
249 uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) {
250 FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset);
251 if (frame == nullptr) {
252 ALOGE("updateAcquireFence: Did not find frame.");
253 return;
254 }
255
256 if (acquire->isValid()) {
257 mAcquireTimeline.push(acquire);
258 frame->acquireFence = std::move(acquire);
259 } else {
260 // If there isn't an acquire fence, assume that buffer was
261 // ready for the consumer when posted.
262 frame->acquireFence = std::make_shared<FenceTime>(frame->postedTime);
263 }
264 }
265
applyDelta(const FrameEventHistoryDelta & delta)266 void ProducerFrameEventHistory::applyDelta(
267 const FrameEventHistoryDelta& delta) {
268 mCompositorTiming = delta.mCompositorTiming;
269
270 for (auto& d : delta.mDeltas) {
271 // Avoid out-of-bounds access.
272 if (CC_UNLIKELY(d.mIndex >= mFrames.size())) {
273 ALOGE("applyDelta: Bad index.");
274 return;
275 }
276
277 FrameEvents& frame = mFrames[d.mIndex];
278
279 frame.addPostCompositeCalled = d.mAddPostCompositeCalled != 0;
280 frame.addReleaseCalled = d.mAddReleaseCalled != 0;
281
282 frame.postedTime = d.mPostedTime;
283 frame.requestedPresentTime = d.mRequestedPresentTime;
284 frame.latchTime = d.mLatchTime;
285 frame.firstRefreshStartTime = d.mFirstRefreshStartTime;
286 frame.lastRefreshStartTime = d.mLastRefreshStartTime;
287 frame.dequeueReadyTime = d.mDequeueReadyTime;
288
289 if (frame.frameNumber != d.mFrameNumber) {
290 // We got a new frame. Initialize some of the fields.
291 frame.frameNumber = d.mFrameNumber;
292 frame.acquireFence = FenceTime::NO_FENCE;
293 frame.gpuCompositionDoneFence = FenceTime::NO_FENCE;
294 frame.displayPresentFence = FenceTime::NO_FENCE;
295 frame.releaseFence = FenceTime::NO_FENCE;
296 // The consumer only sends valid frames.
297 frame.valid = true;
298 }
299
300 applyFenceDelta(&mGpuCompositionDoneTimeline,
301 &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
302 applyFenceDelta(&mPresentTimeline,
303 &frame.displayPresentFence, d.mDisplayPresentFence);
304 applyFenceDelta(&mReleaseTimeline,
305 &frame.releaseFence, d.mReleaseFence);
306 }
307 }
308
updateSignalTimes()309 void ProducerFrameEventHistory::updateSignalTimes() {
310 mAcquireTimeline.updateSignalTimes();
311 mGpuCompositionDoneTimeline.updateSignalTimes();
312 mPresentTimeline.updateSignalTimes();
313 mReleaseTimeline.updateSignalTimes();
314 }
315
applyFenceDelta(FenceTimeline * timeline,std::shared_ptr<FenceTime> * dst,const FenceTime::Snapshot & src) const316 void ProducerFrameEventHistory::applyFenceDelta(FenceTimeline* timeline,
317 std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) const {
318 if (CC_UNLIKELY(dst == nullptr || dst->get() == nullptr)) {
319 ALOGE("applyFenceDelta: dst is null.");
320 return;
321 }
322
323 switch (src.state) {
324 case FenceTime::Snapshot::State::EMPTY:
325 return;
326 case FenceTime::Snapshot::State::FENCE:
327 ALOGE_IF((*dst)->isValid(), "applyFenceDelta: Unexpected fence.");
328 *dst = createFenceTime(src.fence);
329 timeline->push(*dst);
330 return;
331 case FenceTime::Snapshot::State::SIGNAL_TIME:
332 if ((*dst)->isValid()) {
333 (*dst)->applyTrustedSnapshot(src);
334 } else {
335 *dst = std::make_shared<FenceTime>(src.signalTime);
336 }
337 return;
338 }
339 }
340
createFenceTime(const sp<Fence> & fence) const341 std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime(
342 const sp<Fence>& fence) const {
343 return std::make_shared<FenceTime>(fence);
344 }
345
346
347 // ============================================================================
348 // ConsumerFrameEventHistory
349 // ============================================================================
350
351 ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
352
onDisconnect()353 void ConsumerFrameEventHistory::onDisconnect() {
354 mCurrentConnectId++;
355 mProducerWantsEvents = false;
356 }
357
initializeCompositorTiming(const CompositorTiming & compositorTiming)358 void ConsumerFrameEventHistory::initializeCompositorTiming(
359 const CompositorTiming& compositorTiming) {
360 mCompositorTiming = compositorTiming;
361 }
362
addQueue(const NewFrameEventsEntry & newEntry)363 void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
364 // Overwrite all fields of the frame with default values unless set here.
365 FrameEvents newTimestamps;
366 newTimestamps.connectId = mCurrentConnectId;
367 newTimestamps.frameNumber = newEntry.frameNumber;
368 newTimestamps.postedTime = newEntry.postedTime;
369 newTimestamps.requestedPresentTime = newEntry.requestedPresentTime;
370 newTimestamps.acquireFence = newEntry.acquireFence;
371 newTimestamps.valid = true;
372 mFrames[mQueueOffset] = newTimestamps;
373
374 // Note: We avoid sending the acquire fence back to the caller since
375 // they have the original one already, so there is no need to set the
376 // acquire dirty bit.
377 mFramesDirty[mQueueOffset].setDirty<FrameEvent::POSTED>();
378
379 mQueueOffset = (mQueueOffset + 1) % mFrames.size();
380 }
381
addLatch(uint64_t frameNumber,nsecs_t latchTime)382 void ConsumerFrameEventHistory::addLatch(
383 uint64_t frameNumber, nsecs_t latchTime) {
384 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
385 if (frame == nullptr) {
386 ALOGE_IF(mProducerWantsEvents, "addLatch: Did not find frame.");
387 return;
388 }
389 frame->latchTime = latchTime;
390 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LATCH>();
391 }
392
addPreComposition(uint64_t frameNumber,nsecs_t refreshStartTime)393 void ConsumerFrameEventHistory::addPreComposition(
394 uint64_t frameNumber, nsecs_t refreshStartTime) {
395 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
396 if (frame == nullptr) {
397 ALOGE_IF(mProducerWantsEvents,
398 "addPreComposition: Did not find frame.");
399 return;
400 }
401 frame->lastRefreshStartTime = refreshStartTime;
402 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>();
403 if (!FrameEvents::isValidTimestamp(frame->firstRefreshStartTime)) {
404 frame->firstRefreshStartTime = refreshStartTime;
405 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>();
406 }
407 }
408
addPostComposition(uint64_t frameNumber,const std::shared_ptr<FenceTime> & gpuCompositionDone,const std::shared_ptr<FenceTime> & displayPresent,const CompositorTiming & compositorTiming)409 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
410 const std::shared_ptr<FenceTime>& gpuCompositionDone,
411 const std::shared_ptr<FenceTime>& displayPresent,
412 const CompositorTiming& compositorTiming) {
413 mCompositorTiming = compositorTiming;
414
415 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
416 if (frame == nullptr) {
417 ALOGE_IF(mProducerWantsEvents,
418 "addPostComposition: Did not find frame.");
419 return;
420 }
421 // Only get GPU and present info for the first composite.
422 if (!frame->addPostCompositeCalled) {
423 frame->addPostCompositeCalled = true;
424 frame->gpuCompositionDoneFence = gpuCompositionDone;
425 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::GPU_COMPOSITION_DONE>();
426 if (!frame->displayPresentFence->isValid()) {
427 frame->displayPresentFence = displayPresent;
428 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::DISPLAY_PRESENT>();
429 }
430 }
431 }
432
addRelease(uint64_t frameNumber,nsecs_t dequeueReadyTime,std::shared_ptr<FenceTime> && release)433 void ConsumerFrameEventHistory::addRelease(uint64_t frameNumber,
434 nsecs_t dequeueReadyTime, std::shared_ptr<FenceTime>&& release) {
435 FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
436 if (frame == nullptr) {
437 ALOGE_IF(mProducerWantsEvents, "addRelease: Did not find frame.");
438 return;
439 }
440 frame->addReleaseCalled = true;
441 frame->dequeueReadyTime = dequeueReadyTime;
442 frame->releaseFence = std::move(release);
443 mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
444 }
445
getFrameDelta(FrameEventHistoryDelta * delta,const std::array<FrameEvents,MAX_FRAME_HISTORY>::iterator & frame)446 void ConsumerFrameEventHistory::getFrameDelta(
447 FrameEventHistoryDelta* delta,
448 const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame) {
449 mProducerWantsEvents = true;
450 size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
451 if (mFramesDirty[i].anyDirty()) {
452 // Make sure only to send back deltas for the current connection
453 // since the producer won't have the correct state to apply a delta
454 // from a previous connection.
455 if (mFrames[i].connectId == mCurrentConnectId) {
456 delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
457 }
458 mFramesDirty[i].reset();
459 }
460 }
461
getAndResetDelta(FrameEventHistoryDelta * delta)462 void ConsumerFrameEventHistory::getAndResetDelta(
463 FrameEventHistoryDelta* delta) {
464 mProducerWantsEvents = true;
465 delta->mCompositorTiming = mCompositorTiming;
466
467 // Write these in order of frame number so that it is easy to
468 // add them to a FenceTimeline in the proper order producer side.
469 delta->mDeltas.reserve(mFramesDirty.size());
470 auto earliestFrame = std::min_element(
471 mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
472 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
473 getFrameDelta(delta, frame);
474 }
475 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
476 getFrameDelta(delta, frame);
477 }
478 }
479
480
481 // ============================================================================
482 // FrameEventsDelta
483 // ============================================================================
484
FrameEventsDelta(size_t index,const FrameEvents & frameTimestamps,const FrameEventDirtyFields & dirtyFields)485 FrameEventsDelta::FrameEventsDelta(
486 size_t index,
487 const FrameEvents& frameTimestamps,
488 const FrameEventDirtyFields& dirtyFields)
489 : mIndex(index),
490 mFrameNumber(frameTimestamps.frameNumber),
491 mAddPostCompositeCalled(frameTimestamps.addPostCompositeCalled),
492 mAddReleaseCalled(frameTimestamps.addReleaseCalled),
493 mPostedTime(frameTimestamps.postedTime),
494 mRequestedPresentTime(frameTimestamps.requestedPresentTime),
495 mLatchTime(frameTimestamps.latchTime),
496 mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
497 mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime),
498 mDequeueReadyTime(frameTimestamps.dequeueReadyTime) {
499 if (dirtyFields.isDirty<FrameEvent::GPU_COMPOSITION_DONE>()) {
500 mGpuCompositionDoneFence =
501 frameTimestamps.gpuCompositionDoneFence->getSnapshot();
502 }
503 if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) {
504 mDisplayPresentFence =
505 frameTimestamps.displayPresentFence->getSnapshot();
506 }
507 if (dirtyFields.isDirty<FrameEvent::RELEASE>()) {
508 mReleaseFence = frameTimestamps.releaseFence->getSnapshot();
509 }
510 }
511
minFlattenedSize()512 constexpr size_t FrameEventsDelta::minFlattenedSize() {
513 return sizeof(FrameEventsDelta::mFrameNumber) +
514 sizeof(uint16_t) + // mIndex
515 sizeof(uint8_t) + // mAddPostCompositeCalled
516 sizeof(uint8_t) + // mAddReleaseCalled
517 sizeof(FrameEventsDelta::mPostedTime) +
518 sizeof(FrameEventsDelta::mRequestedPresentTime) +
519 sizeof(FrameEventsDelta::mLatchTime) +
520 sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
521 sizeof(FrameEventsDelta::mLastRefreshStartTime) +
522 sizeof(FrameEventsDelta::mDequeueReadyTime);
523 }
524
525 // Flattenable implementation
getFlattenedSize() const526 size_t FrameEventsDelta::getFlattenedSize() const {
527 auto fences = allFences(this);
528 return minFlattenedSize() +
529 std::accumulate(fences.begin(), fences.end(), size_t(0),
530 [](size_t a, const FenceTime::Snapshot* fence) {
531 return a + fence->getFlattenedSize();
532 });
533 }
534
getFdCount() const535 size_t FrameEventsDelta::getFdCount() const {
536 auto fences = allFences(this);
537 return std::accumulate(fences.begin(), fences.end(), size_t(0),
538 [](size_t a, const FenceTime::Snapshot* fence) {
539 return a + fence->getFdCount();
540 });
541 }
542
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const543 status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds,
544 size_t& count) const {
545 if (size < getFlattenedSize() || count < getFdCount()) {
546 return NO_MEMORY;
547 }
548
549 if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY ||
550 mIndex > std::numeric_limits<uint16_t>::max()) {
551 return BAD_VALUE;
552 }
553
554 FlattenableUtils::write(buffer, size, mFrameNumber);
555
556 // These are static_cast to uint16_t/uint8_t for alignment.
557 FlattenableUtils::write(buffer, size, static_cast<uint16_t>(mIndex));
558 FlattenableUtils::write(
559 buffer, size, static_cast<uint8_t>(mAddPostCompositeCalled));
560 FlattenableUtils::write(
561 buffer, size, static_cast<uint8_t>(mAddReleaseCalled));
562
563 FlattenableUtils::write(buffer, size, mPostedTime);
564 FlattenableUtils::write(buffer, size, mRequestedPresentTime);
565 FlattenableUtils::write(buffer, size, mLatchTime);
566 FlattenableUtils::write(buffer, size, mFirstRefreshStartTime);
567 FlattenableUtils::write(buffer, size, mLastRefreshStartTime);
568 FlattenableUtils::write(buffer, size, mDequeueReadyTime);
569
570 // Fences
571 for (auto fence : allFences(this)) {
572 status_t status = fence->flatten(buffer, size, fds, count);
573 if (status != NO_ERROR) {
574 return status;
575 }
576 }
577 return NO_ERROR;
578 }
579
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)580 status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size,
581 int const*& fds, size_t& count) {
582 if (size < minFlattenedSize()) {
583 return NO_MEMORY;
584 }
585
586 FlattenableUtils::read(buffer, size, mFrameNumber);
587
588 // These were written as uint16_t/uint8_t for alignment.
589 uint16_t temp16 = 0;
590 FlattenableUtils::read(buffer, size, temp16);
591 mIndex = temp16;
592 if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY) {
593 return BAD_VALUE;
594 }
595 uint8_t temp8 = 0;
596 FlattenableUtils::read(buffer, size, temp8);
597 mAddPostCompositeCalled = static_cast<bool>(temp8);
598 FlattenableUtils::read(buffer, size, temp8);
599 mAddReleaseCalled = static_cast<bool>(temp8);
600
601 FlattenableUtils::read(buffer, size, mPostedTime);
602 FlattenableUtils::read(buffer, size, mRequestedPresentTime);
603 FlattenableUtils::read(buffer, size, mLatchTime);
604 FlattenableUtils::read(buffer, size, mFirstRefreshStartTime);
605 FlattenableUtils::read(buffer, size, mLastRefreshStartTime);
606 FlattenableUtils::read(buffer, size, mDequeueReadyTime);
607
608 // Fences
609 for (auto fence : allFences(this)) {
610 status_t status = fence->unflatten(buffer, size, fds, count);
611 if (status != NO_ERROR) {
612 return status;
613 }
614 }
615 return NO_ERROR;
616 }
617
618
619 // ============================================================================
620 // FrameEventHistoryDelta
621 // ============================================================================
622
operator =(FrameEventHistoryDelta && src)623 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
624 FrameEventHistoryDelta&& src) {
625 mCompositorTiming = src.mCompositorTiming;
626
627 if (CC_UNLIKELY(!mDeltas.empty())) {
628 ALOGE("FrameEventHistoryDelta assign clobbering history.");
629 }
630 mDeltas = std::move(src.mDeltas);
631 ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty.");
632 return *this;
633 }
634
minFlattenedSize()635 constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
636 return sizeof(uint32_t) + // mDeltas.size()
637 sizeof(mCompositorTiming);
638 }
639
getFlattenedSize() const640 size_t FrameEventHistoryDelta::getFlattenedSize() const {
641 return minFlattenedSize() +
642 std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
643 [](size_t a, const FrameEventsDelta& delta) {
644 return a + delta.getFlattenedSize();
645 });
646 }
647
getFdCount() const648 size_t FrameEventHistoryDelta::getFdCount() const {
649 return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
650 [](size_t a, const FrameEventsDelta& delta) {
651 return a + delta.getFdCount();
652 });
653 }
654
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const655 status_t FrameEventHistoryDelta::flatten(
656 void*& buffer, size_t& size, int*& fds, size_t& count) const {
657 if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) {
658 return BAD_VALUE;
659 }
660 if (size < getFlattenedSize()) {
661 return NO_MEMORY;
662 }
663
664 FlattenableUtils::write(buffer, size, mCompositorTiming);
665
666 FlattenableUtils::write(
667 buffer, size, static_cast<uint32_t>(mDeltas.size()));
668 for (auto& d : mDeltas) {
669 status_t status = d.flatten(buffer, size, fds, count);
670 if (status != NO_ERROR) {
671 return status;
672 }
673 }
674 return NO_ERROR;
675 }
676
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)677 status_t FrameEventHistoryDelta::unflatten(
678 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
679 if (size < minFlattenedSize()) {
680 return NO_MEMORY;
681 }
682
683 FlattenableUtils::read(buffer, size, mCompositorTiming);
684
685 uint32_t deltaCount = 0;
686 FlattenableUtils::read(buffer, size, deltaCount);
687 if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
688 return BAD_VALUE;
689 }
690 mDeltas.resize(deltaCount);
691 for (auto& d : mDeltas) {
692 status_t status = d.unflatten(buffer, size, fds, count);
693 if (status != NO_ERROR) {
694 return status;
695 }
696 }
697 return NO_ERROR;
698 }
699
700
701 } // namespace android
702