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