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