• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anonfbe82ffc0111::FrameNumberEqual162     explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
operator ()android::__anonfbe82ffc0111::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 
setProducerWantsEvents()367 void ConsumerFrameEventHistory::setProducerWantsEvents() {
368     mProducerWantsEvents = true;
369 }
370 
initializeCompositorTiming(const CompositorTiming & compositorTiming)371 void ConsumerFrameEventHistory::initializeCompositorTiming(
372         const CompositorTiming& compositorTiming) {
373     mCompositorTiming = compositorTiming;
374 }
375 
addQueue(const NewFrameEventsEntry & newEntry)376 void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
377     // Overwrite all fields of the frame with default values unless set here.
378     FrameEvents newTimestamps;
379     newTimestamps.connectId = mCurrentConnectId;
380     newTimestamps.frameNumber = newEntry.frameNumber;
381     newTimestamps.postedTime = newEntry.postedTime;
382     newTimestamps.requestedPresentTime = newEntry.requestedPresentTime;
383     newTimestamps.acquireFence = newEntry.acquireFence;
384     newTimestamps.valid = true;
385     mFrames[mQueueOffset] = newTimestamps;
386 
387     // Note: We avoid sending the acquire fence back to the caller since
388     // they have the original one already, so there is no need to set the
389     // acquire dirty bit.
390     mFramesDirty[mQueueOffset].setDirty<FrameEvent::POSTED>();
391 
392     mQueueOffset = (mQueueOffset + 1) % mFrames.size();
393 }
394 
addLatch(uint64_t frameNumber,nsecs_t latchTime)395 void ConsumerFrameEventHistory::addLatch(
396         uint64_t frameNumber, nsecs_t latchTime) {
397     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
398     if (frame == nullptr) {
399         ALOGE_IF(mProducerWantsEvents, "addLatch: Did not find frame.");
400         return;
401     }
402     frame->latchTime = latchTime;
403     mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LATCH>();
404 }
405 
addPreComposition(uint64_t frameNumber,nsecs_t refreshStartTime)406 void ConsumerFrameEventHistory::addPreComposition(
407         uint64_t frameNumber, nsecs_t refreshStartTime) {
408     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
409     if (frame == nullptr) {
410         ALOGE_IF(mProducerWantsEvents,
411                 "addPreComposition: Did not find frame.");
412         return;
413     }
414     frame->lastRefreshStartTime = refreshStartTime;
415     mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>();
416     if (!FrameEvents::isValidTimestamp(frame->firstRefreshStartTime)) {
417         frame->firstRefreshStartTime = refreshStartTime;
418         mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>();
419     }
420 }
421 
addPostComposition(uint64_t frameNumber,const std::shared_ptr<FenceTime> & gpuCompositionDone,const std::shared_ptr<FenceTime> & displayPresent,const CompositorTiming & compositorTiming)422 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
423         const std::shared_ptr<FenceTime>& gpuCompositionDone,
424         const std::shared_ptr<FenceTime>& displayPresent,
425         const CompositorTiming& compositorTiming) {
426     mCompositorTiming = compositorTiming;
427 
428     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
429     if (frame == nullptr) {
430         ALOGE_IF(mProducerWantsEvents,
431                 "addPostComposition: Did not find frame.");
432         return;
433     }
434     // Only get GPU and present info for the first composite.
435     if (!frame->addPostCompositeCalled) {
436         frame->addPostCompositeCalled = true;
437         frame->gpuCompositionDoneFence = gpuCompositionDone;
438         mFramesDirty[mCompositionOffset].setDirty<FrameEvent::GPU_COMPOSITION_DONE>();
439         if (!frame->displayPresentFence->isValid()) {
440             frame->displayPresentFence = displayPresent;
441             mFramesDirty[mCompositionOffset].setDirty<FrameEvent::DISPLAY_PRESENT>();
442         }
443     }
444 }
445 
addRelease(uint64_t frameNumber,nsecs_t dequeueReadyTime,std::shared_ptr<FenceTime> && release)446 void ConsumerFrameEventHistory::addRelease(uint64_t frameNumber,
447         nsecs_t dequeueReadyTime, std::shared_ptr<FenceTime>&& release) {
448     FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
449     if (frame == nullptr) {
450         ALOGE_IF(mProducerWantsEvents, "addRelease: Did not find frame.");
451         return;
452     }
453     frame->addReleaseCalled = true;
454     frame->dequeueReadyTime = dequeueReadyTime;
455     frame->releaseFence = std::move(release);
456     mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
457 }
458 
getFrameDelta(FrameEventHistoryDelta * delta,const std::vector<FrameEvents>::iterator & frame)459 void ConsumerFrameEventHistory::getFrameDelta(FrameEventHistoryDelta* delta,
460                                               const std::vector<FrameEvents>::iterator& frame) {
461     mProducerWantsEvents = true;
462     size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
463     if (mFramesDirty[i].anyDirty()) {
464         // Make sure only to send back deltas for the current connection
465         // since the producer won't have the correct state to apply a delta
466         // from a previous connection.
467         if (mFrames[i].connectId == mCurrentConnectId) {
468             delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
469         }
470         mFramesDirty[i].reset();
471     }
472 }
473 
getAndResetDelta(FrameEventHistoryDelta * delta)474 void ConsumerFrameEventHistory::getAndResetDelta(
475         FrameEventHistoryDelta* delta) {
476     mProducerWantsEvents = true;
477     delta->mCompositorTiming = mCompositorTiming;
478 
479     // Write these in order of frame number so that it is easy to
480     // add them to a FenceTimeline in the proper order producer side.
481     delta->mDeltas.reserve(mFramesDirty.size());
482     auto earliestFrame = std::min_element(
483             mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
484     for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
485         getFrameDelta(delta, frame);
486     }
487     for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
488         getFrameDelta(delta, frame);
489     }
490 }
491 
492 
493 // ============================================================================
494 // FrameEventsDelta
495 // ============================================================================
496 
FrameEventsDelta(size_t index,const FrameEvents & frameTimestamps,const FrameEventDirtyFields & dirtyFields)497 FrameEventsDelta::FrameEventsDelta(
498         size_t index,
499         const FrameEvents& frameTimestamps,
500         const FrameEventDirtyFields& dirtyFields)
501     : mIndex(index),
502       mFrameNumber(frameTimestamps.frameNumber),
503       mAddPostCompositeCalled(frameTimestamps.addPostCompositeCalled),
504       mAddReleaseCalled(frameTimestamps.addReleaseCalled),
505       mPostedTime(frameTimestamps.postedTime),
506       mRequestedPresentTime(frameTimestamps.requestedPresentTime),
507       mLatchTime(frameTimestamps.latchTime),
508       mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
509       mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime),
510       mDequeueReadyTime(frameTimestamps.dequeueReadyTime) {
511     if (dirtyFields.isDirty<FrameEvent::GPU_COMPOSITION_DONE>()) {
512         mGpuCompositionDoneFence =
513                 frameTimestamps.gpuCompositionDoneFence->getSnapshot();
514     }
515     if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) {
516         mDisplayPresentFence =
517                 frameTimestamps.displayPresentFence->getSnapshot();
518     }
519     if (dirtyFields.isDirty<FrameEvent::RELEASE>()) {
520         mReleaseFence = frameTimestamps.releaseFence->getSnapshot();
521     }
522 }
523 
minFlattenedSize()524 constexpr size_t FrameEventsDelta::minFlattenedSize() {
525     return sizeof(FrameEventsDelta::mFrameNumber) +
526             sizeof(uint16_t) + // mIndex
527             sizeof(uint8_t) + // mAddPostCompositeCalled
528             sizeof(uint8_t) + // mAddReleaseCalled
529             sizeof(FrameEventsDelta::mPostedTime) +
530             sizeof(FrameEventsDelta::mRequestedPresentTime) +
531             sizeof(FrameEventsDelta::mLatchTime) +
532             sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
533             sizeof(FrameEventsDelta::mLastRefreshStartTime) +
534             sizeof(FrameEventsDelta::mDequeueReadyTime);
535 }
536 
537 // Flattenable implementation
getFlattenedSize() const538 size_t FrameEventsDelta::getFlattenedSize() const {
539     auto fences = allFences(this);
540     return minFlattenedSize() +
541             std::accumulate(fences.begin(), fences.end(), size_t(0),
542                     [](size_t a, const FenceTime::Snapshot* fence) {
543                             return a + fence->getFlattenedSize();
544                     });
545 }
546 
getFdCount() const547 size_t FrameEventsDelta::getFdCount() const {
548     auto fences = allFences(this);
549     return std::accumulate(fences.begin(), fences.end(), size_t(0),
550             [](size_t a, const FenceTime::Snapshot* fence) {
551                 return a + fence->getFdCount();
552             });
553 }
554 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const555 status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds,
556             size_t& count) const {
557     if (size < getFlattenedSize() || count < getFdCount()) {
558         return NO_MEMORY;
559     }
560 
561     if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY ||
562             mIndex > std::numeric_limits<uint16_t>::max()) {
563         return BAD_VALUE;
564     }
565 
566     FlattenableUtils::write(buffer, size, mFrameNumber);
567 
568     // These are static_cast to uint16_t/uint8_t for alignment.
569     FlattenableUtils::write(buffer, size, static_cast<uint16_t>(mIndex));
570     FlattenableUtils::write(
571             buffer, size, static_cast<uint8_t>(mAddPostCompositeCalled));
572     FlattenableUtils::write(
573             buffer, size, static_cast<uint8_t>(mAddReleaseCalled));
574 
575     FlattenableUtils::write(buffer, size, mPostedTime);
576     FlattenableUtils::write(buffer, size, mRequestedPresentTime);
577     FlattenableUtils::write(buffer, size, mLatchTime);
578     FlattenableUtils::write(buffer, size, mFirstRefreshStartTime);
579     FlattenableUtils::write(buffer, size, mLastRefreshStartTime);
580     FlattenableUtils::write(buffer, size, mDequeueReadyTime);
581 
582     // Fences
583     for (auto fence : allFences(this)) {
584         status_t status = fence->flatten(buffer, size, fds, count);
585         if (status != NO_ERROR) {
586             return status;
587         }
588     }
589     return NO_ERROR;
590 }
591 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)592 status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size,
593             int const*& fds, size_t& count) {
594     if (size < minFlattenedSize()) {
595         return NO_MEMORY;
596     }
597 
598     FlattenableUtils::read(buffer, size, mFrameNumber);
599 
600     // These were written as uint16_t/uint8_t for alignment.
601     uint16_t temp16 = 0;
602     FlattenableUtils::read(buffer, size, temp16);
603     mIndex = temp16;
604     if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY) {
605         return BAD_VALUE;
606     }
607     uint8_t temp8 = 0;
608     FlattenableUtils::read(buffer, size, temp8);
609     mAddPostCompositeCalled = static_cast<bool>(temp8);
610     FlattenableUtils::read(buffer, size, temp8);
611     mAddReleaseCalled = static_cast<bool>(temp8);
612 
613     FlattenableUtils::read(buffer, size, mPostedTime);
614     FlattenableUtils::read(buffer, size, mRequestedPresentTime);
615     FlattenableUtils::read(buffer, size, mLatchTime);
616     FlattenableUtils::read(buffer, size, mFirstRefreshStartTime);
617     FlattenableUtils::read(buffer, size, mLastRefreshStartTime);
618     FlattenableUtils::read(buffer, size, mDequeueReadyTime);
619 
620     // Fences
621     for (auto fence : allFences(this)) {
622         status_t status = fence->unflatten(buffer, size, fds, count);
623         if (status != NO_ERROR) {
624             return status;
625         }
626     }
627     return NO_ERROR;
628 }
629 
630 
631 // ============================================================================
632 // FrameEventHistoryDelta
633 // ============================================================================
634 
operator =(FrameEventHistoryDelta && src)635 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
636         FrameEventHistoryDelta&& src) noexcept {
637     mCompositorTiming = src.mCompositorTiming;
638 
639     if (CC_UNLIKELY(!mDeltas.empty())) {
640         ALOGE("FrameEventHistoryDelta assign clobbering history.");
641     }
642     mDeltas = std::move(src.mDeltas);
643     return *this;
644 }
645 
minFlattenedSize()646 constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
647     return sizeof(uint32_t) + // mDeltas.size()
648             sizeof(mCompositorTiming);
649 }
650 
getFlattenedSize() const651 size_t FrameEventHistoryDelta::getFlattenedSize() const {
652     return minFlattenedSize() +
653             std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
654                     [](size_t a, const FrameEventsDelta& delta) {
655                             return a + delta.getFlattenedSize();
656                     });
657 }
658 
getFdCount() const659 size_t FrameEventHistoryDelta::getFdCount() const {
660     return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
661             [](size_t a, const FrameEventsDelta& delta) {
662                     return a + delta.getFdCount();
663             });
664 }
665 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const666 status_t FrameEventHistoryDelta::flatten(
667             void*& buffer, size_t& size, int*& fds, size_t& count) const {
668     if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) {
669         return BAD_VALUE;
670     }
671     if (size < getFlattenedSize()) {
672         return NO_MEMORY;
673     }
674 
675     FlattenableUtils::write(buffer, size, mCompositorTiming);
676 
677     FlattenableUtils::write(
678             buffer, size, static_cast<uint32_t>(mDeltas.size()));
679     for (auto& d : mDeltas) {
680         status_t status = d.flatten(buffer, size, fds, count);
681         if (status != NO_ERROR) {
682             return status;
683         }
684     }
685     return NO_ERROR;
686 }
687 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)688 status_t FrameEventHistoryDelta::unflatten(
689             void const*& buffer, size_t& size, int const*& fds, size_t& count) {
690     if (size < minFlattenedSize()) {
691         return NO_MEMORY;
692     }
693 
694     FlattenableUtils::read(buffer, size, mCompositorTiming);
695 
696     uint32_t deltaCount = 0;
697     FlattenableUtils::read(buffer, size, deltaCount);
698     if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
699         return BAD_VALUE;
700     }
701     mDeltas.resize(deltaCount);
702     for (auto& d : mDeltas) {
703         status_t status = d.unflatten(buffer, size, fds, count);
704         if (status != NO_ERROR) {
705             return status;
706         }
707     }
708     return NO_ERROR;
709 }
710 
711 
712 } // namespace android
713