Home | History | Annotate | Download | only in gui
      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 
     37 bool FrameEvents::hasPostedInfo() const {
     38     return FrameEvents::isValidTimestamp(postedTime);
     39 }
     40 
     41 bool FrameEvents::hasRequestedPresentInfo() const {
     42     return FrameEvents::isValidTimestamp(requestedPresentTime);
     43 }
     44 
     45 bool FrameEvents::hasLatchInfo() const {
     46     return FrameEvents::isValidTimestamp(latchTime);
     47 }
     48 
     49 bool FrameEvents::hasFirstRefreshStartInfo() const {
     50     return FrameEvents::isValidTimestamp(firstRefreshStartTime);
     51 }
     52 
     53 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 
     59 bool FrameEvents::hasDequeueReadyInfo() const {
     60     return FrameEvents::isValidTimestamp(dequeueReadyTime);
     61 }
     62 
     63 bool FrameEvents::hasAcquireInfo() const {
     64     return acquireFence->isValid();
     65 }
     66 
     67 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 
     73 bool FrameEvents::hasDisplayPresentInfo() const {
     74     // We may not get a displayPresent in addPostComposite for HWC1.
     75     return addPostCompositeCalled;
     76 }
     77 
     78 bool FrameEvents::hasReleaseInfo() const {
     79     return addReleaseCalled;
     80 }
     81 
     82 void FrameEvents::checkFencesForCompletion() {
     83     acquireFence->getSignalTime();
     84     gpuCompositionDoneFence->getSignalTime();
     85     displayPresentFence->getSignalTime();
     86     releaseFence->getSignalTime();
     87 }
     88 
     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 
    104 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 {
    161     FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
    162     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 
    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 
    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 
    194 void FrameEventHistory::checkFencesForCompletion() {
    195     for (auto& frame : mFrames) {
    196         frame.checkFencesForCompletion();
    197     }
    198 }
    199 
    200 // Uses !|valid| as the MSB.
    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 
    209 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 
    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 
    242 nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline(
    243         const nsecs_t now) const{
    244     return snapToNextTick(
    245             now, mCompositorTiming.deadline, mCompositorTiming.interval);
    246 }
    247 
    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 
    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 
    309 void ProducerFrameEventHistory::updateSignalTimes() {
    310     mAcquireTimeline.updateSignalTimes();
    311     mGpuCompositionDoneTimeline.updateSignalTimes();
    312     mPresentTimeline.updateSignalTimes();
    313     mReleaseTimeline.updateSignalTimes();
    314 }
    315 
    316 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 
    341 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 
    353 void ConsumerFrameEventHistory::onDisconnect() {
    354     mCurrentConnectId++;
    355     mProducerWantsEvents = false;
    356 }
    357 
    358 void ConsumerFrameEventHistory::initializeCompositorTiming(
    359         const CompositorTiming& compositorTiming) {
    360     mCompositorTiming = compositorTiming;
    361 }
    362 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    526 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 
    535 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 
    543 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 
    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 
    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     return *this;
    632 }
    633 
    634 constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
    635     return sizeof(uint32_t) + // mDeltas.size()
    636             sizeof(mCompositorTiming);
    637 }
    638 
    639 size_t FrameEventHistoryDelta::getFlattenedSize() const {
    640     return minFlattenedSize() +
    641             std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
    642                     [](size_t a, const FrameEventsDelta& delta) {
    643                             return a + delta.getFlattenedSize();
    644                     });
    645 }
    646 
    647 size_t FrameEventHistoryDelta::getFdCount() const {
    648     return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
    649             [](size_t a, const FrameEventsDelta& delta) {
    650                     return a + delta.getFdCount();
    651             });
    652 }
    653 
    654 status_t FrameEventHistoryDelta::flatten(
    655             void*& buffer, size_t& size, int*& fds, size_t& count) const {
    656     if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) {
    657         return BAD_VALUE;
    658     }
    659     if (size < getFlattenedSize()) {
    660         return NO_MEMORY;
    661     }
    662 
    663     FlattenableUtils::write(buffer, size, mCompositorTiming);
    664 
    665     FlattenableUtils::write(
    666             buffer, size, static_cast<uint32_t>(mDeltas.size()));
    667     for (auto& d : mDeltas) {
    668         status_t status = d.flatten(buffer, size, fds, count);
    669         if (status != NO_ERROR) {
    670             return status;
    671         }
    672     }
    673     return NO_ERROR;
    674 }
    675 
    676 status_t FrameEventHistoryDelta::unflatten(
    677             void const*& buffer, size_t& size, int const*& fds, size_t& count) {
    678     if (size < minFlattenedSize()) {
    679         return NO_MEMORY;
    680     }
    681 
    682     FlattenableUtils::read(buffer, size, mCompositorTiming);
    683 
    684     uint32_t deltaCount = 0;
    685     FlattenableUtils::read(buffer, size, deltaCount);
    686     if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
    687         return BAD_VALUE;
    688     }
    689     mDeltas.resize(deltaCount);
    690     for (auto& d : mDeltas) {
    691         status_t status = d.unflatten(buffer, size, fds, count);
    692         if (status != NO_ERROR) {
    693             return status;
    694         }
    695     }
    696     return NO_ERROR;
    697 }
    698 
    699 
    700 } // namespace android
    701