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