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