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