• 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 <android-base/stringprintf.h>
22 #include <cutils/compiler.h>  // For CC_[UN]LIKELY
23 #include <inttypes.h>
24 #include <utils/Log.h>
25 
26 #include <algorithm>
27 #include <limits>
28 #include <numeric>
29 
30 namespace android {
31 
32 using base::StringAppendF;
33 
34 // ============================================================================
35 // FrameEvents
36 // ============================================================================
37 
hasPostedInfo() const38 bool FrameEvents::hasPostedInfo() const {
39     return FrameEvents::isValidTimestamp(postedTime);
40 }
41 
hasRequestedPresentInfo() const42 bool FrameEvents::hasRequestedPresentInfo() const {
43     return FrameEvents::isValidTimestamp(requestedPresentTime);
44 }
45 
hasLatchInfo() const46 bool FrameEvents::hasLatchInfo() const {
47     return FrameEvents::isValidTimestamp(latchTime);
48 }
49 
hasFirstRefreshStartInfo() const50 bool FrameEvents::hasFirstRefreshStartInfo() const {
51     return FrameEvents::isValidTimestamp(firstRefreshStartTime);
52 }
53 
hasLastRefreshStartInfo() const54 bool FrameEvents::hasLastRefreshStartInfo() const {
55     // The last refresh start time may continue to update until a new frame
56     // is latched. We know we have the final value once the release info is set.
57     return addReleaseCalled;
58 }
59 
hasDequeueReadyInfo() const60 bool FrameEvents::hasDequeueReadyInfo() const {
61     return FrameEvents::isValidTimestamp(dequeueReadyTime);
62 }
63 
hasAcquireInfo() const64 bool FrameEvents::hasAcquireInfo() const {
65     return acquireFence->isValid();
66 }
67 
hasGpuCompositionDoneInfo() const68 bool 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 
hasDisplayPresentInfo() const74 bool FrameEvents::hasDisplayPresentInfo() const {
75     // We may not get a displayPresent in addPostComposite for HWC1.
76     return addPostCompositeCalled;
77 }
78 
hasReleaseInfo() const79 bool FrameEvents::hasReleaseInfo() const {
80     return addReleaseCalled;
81 }
82 
checkFencesForCompletion()83 void FrameEvents::checkFencesForCompletion() {
84     acquireFence->getSignalTime();
85     gpuCompositionDoneFence->getSignalTime();
86     displayPresentFence->getSignalTime();
87     releaseFence->getSignalTime();
88 }
89 
dumpFenceTime(std::string & outString,const char * name,bool pending,const FenceTime & fenceTime)90 static void dumpFenceTime(std::string& outString, const char* name, bool pending,
91                           const FenceTime& fenceTime) {
92     StringAppendF(&outString, "--- %s", name);
93     nsecs_t signalTime = fenceTime.getCachedSignalTime();
94     if (Fence::isValidTimestamp(signalTime)) {
95         StringAppendF(&outString, "%" PRId64 "\n", signalTime);
96     } else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) {
97         outString.append("Pending\n");
98     } else if (&fenceTime == FenceTime::NO_FENCE.get()){
99         outString.append("N/A\n");
100     } else {
101         outString.append("Error\n");
102     }
103 }
104 
dump(std::string & outString) const105 void FrameEvents::dump(std::string& outString) const {
106     if (!valid) {
107         return;
108     }
109 
110     StringAppendF(&outString, "-- Frame %" PRIu64 "\n", frameNumber);
111     StringAppendF(&outString, "--- Posted      \t%" PRId64 "\n", postedTime);
112     StringAppendF(&outString, "--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
113 
114     outString.append("--- Latched     \t");
115     if (FrameEvents::isValidTimestamp(latchTime)) {
116         StringAppendF(&outString, "%" PRId64 "\n", latchTime);
117     } else {
118         outString.append("Pending\n");
119     }
120 
121     outString.append("--- Refresh (First)\t");
122     if (FrameEvents::isValidTimestamp(firstRefreshStartTime)) {
123         StringAppendF(&outString, "%" PRId64 "\n", firstRefreshStartTime);
124     } else {
125         outString.append("Pending\n");
126     }
127 
128     outString.append("--- Refresh (Last)\t");
129     if (FrameEvents::isValidTimestamp(lastRefreshStartTime)) {
130         StringAppendF(&outString, "%" PRId64 "\n", lastRefreshStartTime);
131     } else {
132         outString.append("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.append("--- DequeueReady  \t");
143     if (FrameEvents::isValidTimestamp(dequeueReadyTime)) {
144         StringAppendF(&outString, "%" PRId64 "\n", dequeueReadyTime);
145     } else {
146         outString.append("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 {
FrameNumberEqualandroid::__anon611d9dde0111::FrameNumberEqual161     explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
operator ()android::__anon611d9dde0111::FrameNumberEqual162     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 
getFrame(uint64_t frameNumber)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 
getFrame(uint64_t frameNumber,size_t * iHint)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 
checkFencesForCompletion()194 void FrameEventHistory::checkFencesForCompletion() {
195     for (auto& frame : mFrames) {
196         frame.checkFencesForCompletion();
197     }
198 }
199 
200 // Uses !|valid| as the MSB.
FrameNumberLessThan(const FrameEvents & lhs,const FrameEvents & rhs)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 
dump(std::string & outString) const209 void FrameEventHistory::dump(std::string& outString) const {
210     auto earliestFrame = std::min_element(
211             mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
212     if (!earliestFrame->valid) {
213         outString.append("-- 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 
snapToNextTick(nsecs_t timestamp,nsecs_t tickPhase,nsecs_t tickInterval)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 
getNextCompositeDeadline(const nsecs_t now) const242 nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline(
243         const nsecs_t now) const{
244     return snapToNextTick(
245             now, mCompositorTiming.deadline, mCompositorTiming.interval);
246 }
247 
updateAcquireFence(uint64_t frameNumber,std::shared_ptr<FenceTime> && acquire)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 
applyDelta(const FrameEventHistoryDelta & delta)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 
updateSignalTimes()309 void ProducerFrameEventHistory::updateSignalTimes() {
310     mAcquireTimeline.updateSignalTimes();
311     mGpuCompositionDoneTimeline.updateSignalTimes();
312     mPresentTimeline.updateSignalTimes();
313     mReleaseTimeline.updateSignalTimes();
314 }
315 
applyFenceDelta(FenceTimeline * timeline,std::shared_ptr<FenceTime> * dst,const FenceTime::Snapshot & src) const316 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 
createFenceTime(const sp<Fence> & fence) const341 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 
onDisconnect()353 void ConsumerFrameEventHistory::onDisconnect() {
354     mCurrentConnectId++;
355     mProducerWantsEvents = false;
356 }
357 
initializeCompositorTiming(const CompositorTiming & compositorTiming)358 void ConsumerFrameEventHistory::initializeCompositorTiming(
359         const CompositorTiming& compositorTiming) {
360     mCompositorTiming = compositorTiming;
361 }
362 
addQueue(const NewFrameEventsEntry & newEntry)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 
addLatch(uint64_t frameNumber,nsecs_t latchTime)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 
addPreComposition(uint64_t frameNumber,nsecs_t refreshStartTime)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 
addPostComposition(uint64_t frameNumber,const std::shared_ptr<FenceTime> & gpuCompositionDone,const std::shared_ptr<FenceTime> & displayPresent,const CompositorTiming & compositorTiming)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 
addRelease(uint64_t frameNumber,nsecs_t dequeueReadyTime,std::shared_ptr<FenceTime> && release)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 
getFrameDelta(FrameEventHistoryDelta * delta,const std::array<FrameEvents,MAX_FRAME_HISTORY>::iterator & frame)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 
getAndResetDelta(FrameEventHistoryDelta * delta)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 
FrameEventsDelta(size_t index,const FrameEvents & frameTimestamps,const FrameEventDirtyFields & dirtyFields)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 
minFlattenedSize()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
getFlattenedSize() const526 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 
getFdCount() const535 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 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const543 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 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)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 
operator =(FrameEventHistoryDelta && src)623 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
624         FrameEventHistoryDelta&& src) noexcept {
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 
minFlattenedSize()634 constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
635     return sizeof(uint32_t) + // mDeltas.size()
636             sizeof(mCompositorTiming);
637 }
638 
getFlattenedSize() const639 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 
getFdCount() const647 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 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const654 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 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)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