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