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