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