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::__anon96b2c21a0111::FrameNumberEqual162 explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
operator ()android::__anon96b2c21a0111::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::INITIAL_MAX_FRAME_HISTORY =
172 sysprop::LibGuiProperties::frame_event_history_size().value_or(8);
173
FrameEventHistory()174 FrameEventHistory::FrameEventHistory()
175 : mFrames(std::vector<FrameEvents>(INITIAL_MAX_FRAME_HISTORY)) {}
176
177 FrameEventHistory::~FrameEventHistory() = default;
178
getFrame(uint64_t frameNumber)179 FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) {
180 auto frame = std::find_if(
181 mFrames.begin(), mFrames.end(), FrameNumberEqual(frameNumber));
182 return frame == mFrames.end() ? nullptr : &(*frame);
183 }
184
getFrame(uint64_t frameNumber,size_t * iHint)185 FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber, size_t* iHint) {
186 *iHint = std::min(*iHint, mFrames.size());
187 auto hint = mFrames.begin() + *iHint;
188 auto frame = std::find_if(
189 hint, mFrames.end(), FrameNumberEqual(frameNumber));
190 if (frame == mFrames.end()) {
191 frame = std::find_if(
192 mFrames.begin(), hint, FrameNumberEqual(frameNumber));
193 if (frame == hint) {
194 return nullptr;
195 }
196 }
197 *iHint = static_cast<size_t>(std::distance(mFrames.begin(), frame));
198 return &(*frame);
199 }
200
checkFencesForCompletion()201 void FrameEventHistory::checkFencesForCompletion() {
202 for (auto& frame : mFrames) {
203 frame.checkFencesForCompletion();
204 }
205 }
206
207 // Uses !|valid| as the MSB.
FrameNumberLessThan(const FrameEvents & lhs,const FrameEvents & rhs)208 static bool FrameNumberLessThan(
209 const FrameEvents& lhs, const FrameEvents& rhs) {
210 if (lhs.valid == rhs.valid) {
211 return lhs.frameNumber < rhs.frameNumber;
212 }
213 return lhs.valid;
214 }
215
dump(std::string & outString) const216 void FrameEventHistory::dump(std::string& outString) const {
217 auto earliestFrame = std::min_element(
218 mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
219 if (!earliestFrame->valid) {
220 outString.append("-- N/A\n");
221 return;
222 }
223 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
224 frame->dump(outString);
225 }
226 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
227 frame->dump(outString);
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 // Deltas should have enough reserved capacity for the consumer-side, therefore if there's a
277 // different capacity, we re-sized on the consumer side and now need to resize on the producer
278 // side.
279 if (delta.mDeltas.capacity() > mFrames.capacity()) {
280 resize(delta.mDeltas.capacity());
281 }
282
283 for (auto& d : delta.mDeltas) {
284 // Avoid out-of-bounds access.
285 if (CC_UNLIKELY(d.mIndex >= mFrames.size())) {
286 ALOGE("applyDelta: Bad index.");
287 return;
288 }
289
290 FrameEvents& frame = mFrames[d.mIndex];
291
292 frame.addPostCompositeCalled = d.mAddPostCompositeCalled != 0;
293 frame.addReleaseCalled = d.mAddReleaseCalled != 0;
294
295 frame.postedTime = d.mPostedTime;
296 frame.requestedPresentTime = d.mRequestedPresentTime;
297 frame.latchTime = d.mLatchTime;
298 frame.firstRefreshStartTime = d.mFirstRefreshStartTime;
299 frame.lastRefreshStartTime = d.mLastRefreshStartTime;
300 frame.dequeueReadyTime = d.mDequeueReadyTime;
301
302 if (frame.frameNumber != d.mFrameNumber) {
303 // We got a new frame. Initialize some of the fields.
304 frame.frameNumber = d.mFrameNumber;
305 frame.acquireFence = FenceTime::NO_FENCE;
306 frame.gpuCompositionDoneFence = FenceTime::NO_FENCE;
307 frame.displayPresentFence = FenceTime::NO_FENCE;
308 frame.releaseFence = FenceTime::NO_FENCE;
309 // The consumer only sends valid frames.
310 frame.valid = true;
311 }
312
313 applyFenceDelta(&mGpuCompositionDoneTimeline,
314 &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
315 applyFenceDelta(&mPresentTimeline,
316 &frame.displayPresentFence, d.mDisplayPresentFence);
317 applyFenceDelta(&mReleaseTimeline,
318 &frame.releaseFence, d.mReleaseFence);
319 }
320 }
321
updateSignalTimes()322 void ProducerFrameEventHistory::updateSignalTimes() {
323 mAcquireTimeline.updateSignalTimes();
324 mGpuCompositionDoneTimeline.updateSignalTimes();
325 mPresentTimeline.updateSignalTimes();
326 mReleaseTimeline.updateSignalTimes();
327 }
328
applyFenceDelta(FenceTimeline * timeline,std::shared_ptr<FenceTime> * dst,const FenceTime::Snapshot & src) const329 void ProducerFrameEventHistory::applyFenceDelta(FenceTimeline* timeline,
330 std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) const {
331 if (CC_UNLIKELY(dst == nullptr || dst->get() == nullptr)) {
332 ALOGE("applyFenceDelta: dst is null.");
333 return;
334 }
335
336 switch (src.state) {
337 case FenceTime::Snapshot::State::EMPTY:
338 return;
339 case FenceTime::Snapshot::State::FENCE:
340 ALOGE_IF((*dst)->isValid(), "applyFenceDelta: Unexpected fence.");
341 *dst = createFenceTime(src.fence);
342 timeline->push(*dst);
343 return;
344 case FenceTime::Snapshot::State::SIGNAL_TIME:
345 if ((*dst)->isValid()) {
346 (*dst)->applyTrustedSnapshot(src);
347 } else {
348 *dst = std::make_shared<FenceTime>(src.signalTime);
349 }
350 return;
351 }
352 }
353
createFenceTime(const sp<Fence> & fence) const354 std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime(
355 const sp<Fence>& fence) const {
356 return std::make_shared<FenceTime>(fence);
357 }
358
resize(size_t newSize)359 void ProducerFrameEventHistory::resize(size_t newSize) {
360 // we don't want to drop events by resizing too small, so don't resize in the negative direction
361 if (newSize <= mFrames.size()) {
362 return;
363 }
364
365 // This algorithm for resizing needs to be the same as ConsumerFrameEventHistory::resize,
366 // because the indexes need to match when communicating the FrameEventDeltas.
367
368 // We need to find the oldest frame, because that frame needs to move to index 0 in the new
369 // frame history.
370 size_t oldestFrameIndex = 0;
371 size_t oldestFrameNumber = INT32_MAX;
372 for (size_t i = 0; i < mFrames.size(); ++i) {
373 if (mFrames[i].frameNumber < oldestFrameNumber && mFrames[i].valid) {
374 oldestFrameNumber = mFrames[i].frameNumber;
375 oldestFrameIndex = i;
376 }
377 }
378
379 // move the existing frame information into a new vector, so that the oldest frames are at
380 // index 0, and the latest frames are at the end of the vector
381 std::vector<FrameEvents> newFrames(newSize);
382 size_t oldI = oldestFrameIndex;
383 size_t newI = 0;
384 do {
385 if (mFrames[oldI].valid) {
386 newFrames[newI++] = std::move(mFrames[oldI]);
387 }
388 oldI = (oldI + 1) % mFrames.size();
389 } while (oldI != oldestFrameIndex);
390
391 mFrames = std::move(newFrames);
392 mAcquireOffset = 0; // this is just a hint, so setting this to anything is fine
393 }
394
395 // ============================================================================
396 // ConsumerFrameEventHistory
397 // ============================================================================
398
ConsumerFrameEventHistory()399 ConsumerFrameEventHistory::ConsumerFrameEventHistory()
400 : mFramesDirty(std::vector<FrameEventDirtyFields>(INITIAL_MAX_FRAME_HISTORY)) {}
401
402 ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
403
onDisconnect()404 void ConsumerFrameEventHistory::onDisconnect() {
405 mCurrentConnectId++;
406 mProducerWantsEvents = false;
407 }
408
setProducerWantsEvents()409 void ConsumerFrameEventHistory::setProducerWantsEvents() {
410 mProducerWantsEvents = true;
411 }
412
initializeCompositorTiming(const CompositorTiming & compositorTiming)413 void ConsumerFrameEventHistory::initializeCompositorTiming(
414 const CompositorTiming& compositorTiming) {
415 mCompositorTiming = compositorTiming;
416 }
417
addQueue(const NewFrameEventsEntry & newEntry)418 void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
419 // Overwrite all fields of the frame with default values unless set here.
420 FrameEvents newTimestamps;
421 newTimestamps.connectId = mCurrentConnectId;
422 newTimestamps.frameNumber = newEntry.frameNumber;
423 newTimestamps.postedTime = newEntry.postedTime;
424 newTimestamps.requestedPresentTime = newEntry.requestedPresentTime;
425 newTimestamps.acquireFence = newEntry.acquireFence;
426 newTimestamps.valid = true;
427 mFrames[mQueueOffset] = newTimestamps;
428
429 // Note: We avoid sending the acquire fence back to the caller since
430 // they have the original one already, so there is no need to set the
431 // acquire dirty bit.
432 mFramesDirty[mQueueOffset].setDirty<FrameEvent::POSTED>();
433
434 mQueueOffset = (mQueueOffset + 1) % mFrames.size();
435 }
436
addLatch(uint64_t frameNumber,nsecs_t latchTime)437 void ConsumerFrameEventHistory::addLatch(
438 uint64_t frameNumber, nsecs_t latchTime) {
439 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
440 if (frame == nullptr) {
441 ALOGE_IF(mProducerWantsEvents, "addLatch: Did not find frame.");
442 return;
443 }
444 frame->latchTime = latchTime;
445 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LATCH>();
446 }
447
addPreComposition(uint64_t frameNumber,nsecs_t refreshStartTime)448 void ConsumerFrameEventHistory::addPreComposition(
449 uint64_t frameNumber, nsecs_t refreshStartTime) {
450 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
451 if (frame == nullptr) {
452 ALOGE_IF(mProducerWantsEvents,
453 "addPreComposition: Did not find frame.");
454 return;
455 }
456 frame->lastRefreshStartTime = refreshStartTime;
457 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>();
458 if (!FrameEvents::isValidTimestamp(frame->firstRefreshStartTime)) {
459 frame->firstRefreshStartTime = refreshStartTime;
460 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>();
461 }
462 }
463
addPostComposition(uint64_t frameNumber,const std::shared_ptr<FenceTime> & gpuCompositionDone,const std::shared_ptr<FenceTime> & displayPresent,const CompositorTiming & compositorTiming)464 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
465 const std::shared_ptr<FenceTime>& gpuCompositionDone,
466 const std::shared_ptr<FenceTime>& displayPresent,
467 const CompositorTiming& compositorTiming) {
468 mCompositorTiming = compositorTiming;
469
470 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
471 if (frame == nullptr) {
472 ALOGE_IF(mProducerWantsEvents,
473 "addPostComposition: Did not find frame.");
474 return;
475 }
476 // Only get GPU and present info for the first composite.
477 if (!frame->addPostCompositeCalled) {
478 frame->addPostCompositeCalled = true;
479 frame->gpuCompositionDoneFence = gpuCompositionDone;
480 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::GPU_COMPOSITION_DONE>();
481 if (!frame->displayPresentFence->isValid()) {
482 frame->displayPresentFence = displayPresent;
483 mFramesDirty[mCompositionOffset].setDirty<FrameEvent::DISPLAY_PRESENT>();
484 }
485 }
486 }
487
addRelease(uint64_t frameNumber,nsecs_t dequeueReadyTime,std::shared_ptr<FenceTime> && release)488 void ConsumerFrameEventHistory::addRelease(uint64_t frameNumber,
489 nsecs_t dequeueReadyTime, std::shared_ptr<FenceTime>&& release) {
490 FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
491 if (frame == nullptr) {
492 ALOGE_IF(mProducerWantsEvents, "addRelease: Did not find frame.");
493 return;
494 }
495 frame->addReleaseCalled = true;
496 frame->dequeueReadyTime = dequeueReadyTime;
497 frame->releaseFence = std::move(release);
498 mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
499 }
500
getFrameDelta(FrameEventHistoryDelta * delta,const std::vector<FrameEvents>::iterator & frame)501 void ConsumerFrameEventHistory::getFrameDelta(FrameEventHistoryDelta* delta,
502 const std::vector<FrameEvents>::iterator& frame) {
503 mProducerWantsEvents = true;
504 size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
505 if (mFramesDirty[i].anyDirty()) {
506 // Make sure only to send back deltas for the current connection
507 // since the producer won't have the correct state to apply a delta
508 // from a previous connection.
509 if (mFrames[i].connectId == mCurrentConnectId) {
510 delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
511 }
512 mFramesDirty[i].reset();
513 }
514 }
515
getAndResetDelta(FrameEventHistoryDelta * delta)516 void ConsumerFrameEventHistory::getAndResetDelta(
517 FrameEventHistoryDelta* delta) {
518 mProducerWantsEvents = true;
519 delta->mCompositorTiming = mCompositorTiming;
520
521 // Write these in order of frame number so that it is easy to
522 // add them to a FenceTimeline in the proper order producer side.
523 delta->mDeltas.reserve(mFramesDirty.size());
524 auto earliestFrame = std::min_element(
525 mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
526 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
527 getFrameDelta(delta, frame);
528 }
529 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
530 getFrameDelta(delta, frame);
531 }
532 }
533
resize(size_t newSize)534 void ConsumerFrameEventHistory::resize(size_t newSize) {
535 // we don't want to drop events by resizing too small, so don't resize in the negative direction
536 if (newSize <= mFrames.size()) {
537 return;
538 }
539
540 // This algorithm for resizing needs to be the same as ProducerFrameEventHistory::resize,
541 // because the indexes need to match when communicating the FrameEventDeltas.
542
543 // move the existing frame information into a new vector, so that the oldest frames are at
544 // index 0, and the latest frames are towards the end of the vector
545 std::vector<FrameEvents> newFrames(newSize);
546 std::vector<FrameEventDirtyFields> newFramesDirty(newSize);
547 size_t oldestFrameIndex = mQueueOffset;
548 size_t oldI = oldestFrameIndex;
549 size_t newI = 0;
550 do {
551 if (mFrames[oldI].valid) {
552 newFrames[newI] = std::move(mFrames[oldI]);
553 newFramesDirty[newI] = mFramesDirty[oldI];
554 newI += 1;
555 }
556 oldI = (oldI + 1) % mFrames.size();
557 } while (oldI != oldestFrameIndex);
558
559 mFrames = std::move(newFrames);
560 mFramesDirty = std::move(newFramesDirty);
561 mQueueOffset = newI;
562 mCompositionOffset = 0; // this is just a hint, so setting this to anything is fine
563 }
564
565 // ============================================================================
566 // FrameEventsDelta
567 // ============================================================================
568
FrameEventsDelta(size_t index,const FrameEvents & frameTimestamps,const FrameEventDirtyFields & dirtyFields)569 FrameEventsDelta::FrameEventsDelta(
570 size_t index,
571 const FrameEvents& frameTimestamps,
572 const FrameEventDirtyFields& dirtyFields)
573 : mIndex(index),
574 mFrameNumber(frameTimestamps.frameNumber),
575 mAddPostCompositeCalled(frameTimestamps.addPostCompositeCalled),
576 mAddReleaseCalled(frameTimestamps.addReleaseCalled),
577 mPostedTime(frameTimestamps.postedTime),
578 mRequestedPresentTime(frameTimestamps.requestedPresentTime),
579 mLatchTime(frameTimestamps.latchTime),
580 mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
581 mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime),
582 mDequeueReadyTime(frameTimestamps.dequeueReadyTime) {
583 if (dirtyFields.isDirty<FrameEvent::GPU_COMPOSITION_DONE>()) {
584 mGpuCompositionDoneFence =
585 frameTimestamps.gpuCompositionDoneFence->getSnapshot();
586 }
587 if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) {
588 mDisplayPresentFence =
589 frameTimestamps.displayPresentFence->getSnapshot();
590 }
591 if (dirtyFields.isDirty<FrameEvent::RELEASE>()) {
592 mReleaseFence = frameTimestamps.releaseFence->getSnapshot();
593 }
594 }
595
minFlattenedSize()596 constexpr size_t FrameEventsDelta::minFlattenedSize() {
597 return sizeof(FrameEventsDelta::mFrameNumber) +
598 sizeof(uint16_t) + // mIndex
599 sizeof(uint8_t) + // mAddPostCompositeCalled
600 sizeof(uint8_t) + // mAddReleaseCalled
601 sizeof(FrameEventsDelta::mPostedTime) +
602 sizeof(FrameEventsDelta::mRequestedPresentTime) +
603 sizeof(FrameEventsDelta::mLatchTime) +
604 sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
605 sizeof(FrameEventsDelta::mLastRefreshStartTime) +
606 sizeof(FrameEventsDelta::mDequeueReadyTime);
607 }
608
609 // Flattenable implementation
getFlattenedSize() const610 size_t FrameEventsDelta::getFlattenedSize() const {
611 auto fences = allFences(this);
612 return minFlattenedSize() +
613 std::accumulate(fences.begin(), fences.end(), size_t(0),
614 [](size_t a, const FenceTime::Snapshot* fence) {
615 return a + fence->getFlattenedSize();
616 });
617 }
618
getFdCount() const619 size_t FrameEventsDelta::getFdCount() const {
620 auto fences = allFences(this);
621 return std::accumulate(fences.begin(), fences.end(), size_t(0),
622 [](size_t a, const FenceTime::Snapshot* fence) {
623 return a + fence->getFdCount();
624 });
625 }
626
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const627 status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds,
628 size_t& count) const {
629 if (size < getFlattenedSize() || count < getFdCount()) {
630 return NO_MEMORY;
631 }
632
633 if (mIndex >= UINT8_MAX || mIndex < 0) {
634 return BAD_VALUE;
635 }
636
637 FlattenableUtils::write(buffer, size, mFrameNumber);
638
639 // These are static_cast to uint16_t/uint8_t for alignment.
640 FlattenableUtils::write(buffer, size, static_cast<uint16_t>(mIndex));
641 FlattenableUtils::write(
642 buffer, size, static_cast<uint8_t>(mAddPostCompositeCalled));
643 FlattenableUtils::write(
644 buffer, size, static_cast<uint8_t>(mAddReleaseCalled));
645
646 FlattenableUtils::write(buffer, size, mPostedTime);
647 FlattenableUtils::write(buffer, size, mRequestedPresentTime);
648 FlattenableUtils::write(buffer, size, mLatchTime);
649 FlattenableUtils::write(buffer, size, mFirstRefreshStartTime);
650 FlattenableUtils::write(buffer, size, mLastRefreshStartTime);
651 FlattenableUtils::write(buffer, size, mDequeueReadyTime);
652
653 // Fences
654 for (auto fence : allFences(this)) {
655 status_t status = fence->flatten(buffer, size, fds, count);
656 if (status != NO_ERROR) {
657 return status;
658 }
659 }
660 return NO_ERROR;
661 }
662
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)663 status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size,
664 int const*& fds, size_t& count) {
665 if (size < minFlattenedSize()) {
666 return NO_MEMORY;
667 }
668
669 FlattenableUtils::read(buffer, size, mFrameNumber);
670
671 // These were written as uint16_t/uint8_t for alignment.
672 uint16_t temp16 = 0;
673 FlattenableUtils::read(buffer, size, temp16);
674 mIndex = temp16;
675 if (mIndex >= UINT8_MAX) {
676 return BAD_VALUE;
677 }
678 uint8_t temp8 = 0;
679 FlattenableUtils::read(buffer, size, temp8);
680 mAddPostCompositeCalled = static_cast<bool>(temp8);
681 FlattenableUtils::read(buffer, size, temp8);
682 mAddReleaseCalled = static_cast<bool>(temp8);
683
684 FlattenableUtils::read(buffer, size, mPostedTime);
685 FlattenableUtils::read(buffer, size, mRequestedPresentTime);
686 FlattenableUtils::read(buffer, size, mLatchTime);
687 FlattenableUtils::read(buffer, size, mFirstRefreshStartTime);
688 FlattenableUtils::read(buffer, size, mLastRefreshStartTime);
689 FlattenableUtils::read(buffer, size, mDequeueReadyTime);
690
691 // Fences
692 for (auto fence : allFences(this)) {
693 status_t status = fence->unflatten(buffer, size, fds, count);
694 if (status != NO_ERROR) {
695 return status;
696 }
697 }
698 return NO_ERROR;
699 }
700
getFrameNumber() const701 uint64_t FrameEventsDelta::getFrameNumber() const {
702 return mFrameNumber;
703 }
704
getLatchTime(nsecs_t * latchTime) const705 bool FrameEventsDelta::getLatchTime(nsecs_t* latchTime) const {
706 if (mLatchTime == FrameEvents::TIMESTAMP_PENDING) {
707 return false;
708 }
709 *latchTime = mLatchTime;
710 return true;
711 }
712
getDisplayPresentFence(sp<Fence> * fence) const713 bool FrameEventsDelta::getDisplayPresentFence(sp<Fence>* fence) const {
714 if (mDisplayPresentFence.fence == Fence::NO_FENCE) {
715 return false;
716 }
717 *fence = mDisplayPresentFence.fence;
718 return true;
719 }
720
721 // ============================================================================
722 // FrameEventHistoryDelta
723 // ============================================================================
724
operator =(FrameEventHistoryDelta && src)725 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
726 FrameEventHistoryDelta&& src) noexcept {
727 mCompositorTiming = src.mCompositorTiming;
728
729 if (CC_UNLIKELY(!mDeltas.empty())) {
730 ALOGE("FrameEventHistoryDelta assign clobbering history.");
731 }
732 mDeltas = std::move(src.mDeltas);
733 return *this;
734 }
735
minFlattenedSize()736 constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
737 return sizeof(uint32_t) + // mDeltas.size()
738 sizeof(mCompositorTiming);
739 }
740
getFlattenedSize() const741 size_t FrameEventHistoryDelta::getFlattenedSize() const {
742 return minFlattenedSize() +
743 std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
744 [](size_t a, const FrameEventsDelta& delta) {
745 return a + delta.getFlattenedSize();
746 });
747 }
748
getFdCount() const749 size_t FrameEventHistoryDelta::getFdCount() const {
750 return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0),
751 [](size_t a, const FrameEventsDelta& delta) {
752 return a + delta.getFdCount();
753 });
754 }
755
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const756 status_t FrameEventHistoryDelta::flatten(
757 void*& buffer, size_t& size, int*& fds, size_t& count) const {
758 if (mDeltas.size() > UINT8_MAX) {
759 return BAD_VALUE;
760 }
761 if (size < getFlattenedSize()) {
762 return NO_MEMORY;
763 }
764
765 FlattenableUtils::write(buffer, size, mCompositorTiming);
766
767 FlattenableUtils::write(
768 buffer, size, static_cast<uint32_t>(mDeltas.size()));
769 for (auto& d : mDeltas) {
770 status_t status = d.flatten(buffer, size, fds, count);
771 if (status != NO_ERROR) {
772 return status;
773 }
774 }
775 return NO_ERROR;
776 }
777
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)778 status_t FrameEventHistoryDelta::unflatten(
779 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
780 if (size < minFlattenedSize()) {
781 return NO_MEMORY;
782 }
783
784 FlattenableUtils::read(buffer, size, mCompositorTiming);
785
786 uint32_t deltaCount = 0;
787 FlattenableUtils::read(buffer, size, deltaCount);
788 if (deltaCount > UINT8_MAX) {
789 return BAD_VALUE;
790 }
791 mDeltas.resize(deltaCount);
792 for (auto& d : mDeltas) {
793 status_t status = d.unflatten(buffer, size, fds, count);
794 if (status != NO_ERROR) {
795 return status;
796 }
797 }
798 return NO_ERROR;
799 }
800
begin() const801 std::vector<FrameEventsDelta>::const_iterator FrameEventHistoryDelta::begin() const {
802 return mDeltas.begin();
803 }
804
end() const805 std::vector<FrameEventsDelta>::const_iterator FrameEventHistoryDelta::end() const {
806 return mDeltas.end();
807 }
808
809 } // namespace android
810