FrameTimestamps.cpp revision 3d4039d7a291cd9b6f2dd4b46fcdb576f2db3356
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("ConsumerFrameEventHistory::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("ConsumerFrameEventHistory::addPreComposition: " 364 "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("ConsumerFrameEventHistory::addPostComposition: " 381 "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("ConsumerFrameEventHistory::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 size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame)); 424 if (mFramesDirty[i].anyDirty()) { 425 delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]); 426 mFramesDirty[i].reset(); 427 } 428} 429 430void ConsumerFrameEventHistory::getAndResetDelta( 431 FrameEventHistoryDelta* delta) { 432 // Write these in order of frame number so that it is easy to 433 // add them to a FenceTimeline in the proper order producer side. 434 delta->mDeltas.reserve(mFramesDirty.size()); 435 auto earliestFrame = std::min_element( 436 mFrames.begin(), mFrames.end(), &FrameNumberLessThan); 437 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) { 438 getFrameDelta(delta, frame); 439 } 440 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) { 441 getFrameDelta(delta, frame); 442 } 443} 444 445 446// ============================================================================ 447// FrameEventsDelta 448// ============================================================================ 449 450FrameEventsDelta::FrameEventsDelta( 451 size_t index, 452 const FrameEvents& frameTimestamps, 453 const FrameEventDirtyFields& dirtyFields) 454 : mIndex(index), 455 mFrameNumber(frameTimestamps.frameNumber), 456 mAddPostCompositeCalled(frameTimestamps.addPostCompositeCalled), 457 mAddRetireCalled(frameTimestamps.addRetireCalled), 458 mAddReleaseCalled(frameTimestamps.addReleaseCalled), 459 mPostedTime(frameTimestamps.postedTime), 460 mRequestedPresentTime(frameTimestamps.requestedPresentTime), 461 mLatchTime(frameTimestamps.latchTime), 462 mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime), 463 mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) { 464 if (dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>()) { 465 mGpuCompositionDoneFence = 466 frameTimestamps.gpuCompositionDoneFence->getSnapshot(); 467 } 468 if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) { 469 mDisplayPresentFence = 470 frameTimestamps.displayPresentFence->getSnapshot(); 471 } 472 if (dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>()) { 473 mDisplayRetireFence = frameTimestamps.displayRetireFence->getSnapshot(); 474 } 475 if (dirtyFields.isDirty<FrameEvent::RELEASE>()) { 476 mReleaseFence = frameTimestamps.releaseFence->getSnapshot(); 477 } 478} 479 480size_t FrameEventsDelta::minFlattenedSize() { 481 constexpr size_t min = 482 sizeof(FrameEventsDelta::mFrameNumber) + 483 sizeof(uint8_t) + // mIndex 484 sizeof(uint8_t) + // mAddPostCompositeCalled 485 sizeof(uint8_t) + // mAddRetireCalled 486 sizeof(uint8_t) + // mAddReleaseCalled 487 sizeof(FrameEventsDelta::mPostedTime) + 488 sizeof(FrameEventsDelta::mRequestedPresentTime) + 489 sizeof(FrameEventsDelta::mLatchTime) + 490 sizeof(FrameEventsDelta::mFirstRefreshStartTime) + 491 sizeof(FrameEventsDelta::mLastRefreshStartTime); 492 return min; 493} 494 495// Flattenable implementation 496size_t FrameEventsDelta::getFlattenedSize() const { 497 auto fences = allFences(this); 498 return minFlattenedSize() + 499 std::accumulate(fences.begin(), fences.end(), size_t(0), 500 [](size_t a, const FenceTime::Snapshot* fence) { 501 return a + fence->getFlattenedSize(); 502 }); 503} 504 505size_t FrameEventsDelta::getFdCount() const { 506 auto fences = allFences(this); 507 return std::accumulate(fences.begin(), fences.end(), size_t(0), 508 [](size_t a, const FenceTime::Snapshot* fence) { 509 return a + fence->getFdCount(); 510 }); 511} 512 513status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds, 514 size_t& count) const { 515 if (size < getFlattenedSize() || count < getFdCount()) { 516 return NO_MEMORY; 517 } 518 519 if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY || 520 mIndex > std::numeric_limits<uint8_t>::max()) { 521 return BAD_VALUE; 522 } 523 524 FlattenableUtils::write(buffer, size, mFrameNumber); 525 526 // These are static_cast to uint8_t for alignment. 527 FlattenableUtils::write(buffer, size, static_cast<uint8_t>(mIndex)); 528 FlattenableUtils::write( 529 buffer, size, static_cast<uint8_t>(mAddPostCompositeCalled)); 530 FlattenableUtils::write( 531 buffer, size, static_cast<uint8_t>(mAddRetireCalled)); 532 FlattenableUtils::write( 533 buffer, size, static_cast<uint8_t>(mAddReleaseCalled)); 534 535 FlattenableUtils::write(buffer, size, mPostedTime); 536 FlattenableUtils::write(buffer, size, mRequestedPresentTime); 537 FlattenableUtils::write(buffer, size, mLatchTime); 538 FlattenableUtils::write(buffer, size, mFirstRefreshStartTime); 539 FlattenableUtils::write(buffer, size, mLastRefreshStartTime); 540 541 // Fences 542 for (auto fence : allFences(this)) { 543 status_t status = fence->flatten(buffer, size, fds, count); 544 if (status != NO_ERROR) { 545 return status; 546 } 547 } 548 return NO_ERROR; 549} 550 551status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size, 552 int const*& fds, size_t& count) { 553 if (size < minFlattenedSize()) { 554 return NO_MEMORY; 555 } 556 557 FlattenableUtils::read(buffer, size, mFrameNumber); 558 559 // These were written as uint8_t for alignment. 560 uint8_t temp = 0; 561 FlattenableUtils::read(buffer, size, temp); 562 mIndex = temp; 563 if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY) { 564 return BAD_VALUE; 565 } 566 FlattenableUtils::read(buffer, size, temp); 567 mAddPostCompositeCalled = static_cast<bool>(temp); 568 FlattenableUtils::read(buffer, size, temp); 569 mAddRetireCalled = static_cast<bool>(temp); 570 FlattenableUtils::read(buffer, size, temp); 571 mAddReleaseCalled = static_cast<bool>(temp); 572 573 FlattenableUtils::read(buffer, size, mPostedTime); 574 FlattenableUtils::read(buffer, size, mRequestedPresentTime); 575 FlattenableUtils::read(buffer, size, mLatchTime); 576 FlattenableUtils::read(buffer, size, mFirstRefreshStartTime); 577 FlattenableUtils::read(buffer, size, mLastRefreshStartTime); 578 579 // Fences 580 for (auto fence : allFences(this)) { 581 status_t status = fence->unflatten(buffer, size, fds, count); 582 if (status != NO_ERROR) { 583 return status; 584 } 585 } 586 return NO_ERROR; 587} 588 589 590// ============================================================================ 591// FrameEventHistoryDelta 592// ============================================================================ 593 594FrameEventHistoryDelta& FrameEventHistoryDelta::operator=( 595 FrameEventHistoryDelta&& src) { 596 if (CC_UNLIKELY(!mDeltas.empty())) { 597 ALOGE("FrameEventHistoryDelta: Clobbering history."); 598 } 599 mDeltas = std::move(src.mDeltas); 600 ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty."); 601 return *this; 602} 603 604size_t FrameEventHistoryDelta::minFlattenedSize() { 605 return sizeof(uint32_t); 606} 607 608size_t FrameEventHistoryDelta::getFlattenedSize() const { 609 return minFlattenedSize() + 610 std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0), 611 [](size_t a, const FrameEventsDelta& delta) { 612 return a + delta.getFlattenedSize(); 613 }); 614} 615 616size_t FrameEventHistoryDelta::getFdCount() const { 617 return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0), 618 [](size_t a, const FrameEventsDelta& delta) { 619 return a + delta.getFdCount(); 620 }); 621} 622 623status_t FrameEventHistoryDelta::flatten( 624 void*& buffer, size_t& size, int*& fds, size_t& count) const { 625 if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) { 626 return BAD_VALUE; 627 } 628 if (size < getFlattenedSize()) { 629 return NO_MEMORY; 630 } 631 632 FlattenableUtils::write( 633 buffer, size, static_cast<uint32_t>(mDeltas.size())); 634 for (auto& d : mDeltas) { 635 status_t status = d.flatten(buffer, size, fds, count); 636 if (status != NO_ERROR) { 637 return status; 638 } 639 } 640 return NO_ERROR; 641} 642 643status_t FrameEventHistoryDelta::unflatten( 644 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 645 if (size < minFlattenedSize()) { 646 return NO_MEMORY; 647 } 648 649 uint32_t deltaCount = 0; 650 FlattenableUtils::read(buffer, size, deltaCount); 651 if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) { 652 return BAD_VALUE; 653 } 654 mDeltas.resize(deltaCount); 655 for (auto& d : mDeltas) { 656 status_t status = d.unflatten(buffer, size, fds, count); 657 if (status != NO_ERROR) { 658 return status; 659 } 660 } 661 return NO_ERROR; 662} 663 664 665} // namespace android 666