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