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 #undef LOG_TAG 18 #define LOG_TAG "OccupancyTracker" 19 20 #include <gui/OccupancyTracker.h> 21 #include <binder/Parcel.h> 22 #include <utils/String8.h> 23 #include <utils/Trace.h> 24 25 #include <inttypes.h> 26 27 namespace android { 28 29 status_t OccupancyTracker::Segment::writeToParcel(Parcel* parcel) const { 30 status_t result = parcel->writeInt64(totalTime); 31 if (result != OK) { 32 return result; 33 } 34 result = parcel->writeUint64(static_cast<uint64_t>(numFrames)); 35 if (result != OK) { 36 return result; 37 } 38 result = parcel->writeFloat(occupancyAverage); 39 if (result != OK) { 40 return result; 41 } 42 return parcel->writeBool(usedThirdBuffer); 43 } 44 45 status_t OccupancyTracker::Segment::readFromParcel(const Parcel* parcel) { 46 status_t result = parcel->readInt64(&totalTime); 47 if (result != OK) { 48 return result; 49 } 50 uint64_t uintNumFrames = 0; 51 result = parcel->readUint64(&uintNumFrames); 52 if (result != OK) { 53 return result; 54 } 55 numFrames = static_cast<size_t>(uintNumFrames); 56 result = parcel->readFloat(&occupancyAverage); 57 if (result != OK) { 58 return result; 59 } 60 return parcel->readBool(&usedThirdBuffer); 61 } 62 63 void OccupancyTracker::registerOccupancyChange(size_t occupancy) { 64 ATRACE_CALL(); 65 nsecs_t now = systemTime(); 66 nsecs_t delta = now - mLastOccupancyChangeTime; 67 if (delta > NEW_SEGMENT_DELAY) { 68 recordPendingSegment(); 69 } else { 70 mPendingSegment.totalTime += delta; 71 if (mPendingSegment.mOccupancyTimes.count(mLastOccupancy)) { 72 mPendingSegment.mOccupancyTimes[mLastOccupancy] += delta; 73 } else { 74 mPendingSegment.mOccupancyTimes[mLastOccupancy] = delta; 75 } 76 } 77 if (occupancy > mLastOccupancy) { 78 ++mPendingSegment.numFrames; 79 } 80 mLastOccupancyChangeTime = now; 81 mLastOccupancy = occupancy; 82 } 83 84 std::vector<OccupancyTracker::Segment> OccupancyTracker::getSegmentHistory( 85 bool forceFlush) { 86 if (forceFlush) { 87 recordPendingSegment(); 88 } 89 std::vector<Segment> segments(mSegmentHistory.cbegin(), 90 mSegmentHistory.cend()); 91 mSegmentHistory.clear(); 92 return segments; 93 } 94 95 void OccupancyTracker::recordPendingSegment() { 96 // Only record longer segments to get a better measurement of actual double- 97 // vs. triple-buffered time 98 if (mPendingSegment.numFrames > LONG_SEGMENT_THRESHOLD) { 99 float occupancyAverage = 0.0f; 100 bool usedThirdBuffer = false; 101 for (const auto& timePair : mPendingSegment.mOccupancyTimes) { 102 size_t occupancy = timePair.first; 103 float timeRatio = static_cast<float>(timePair.second) / 104 mPendingSegment.totalTime; 105 occupancyAverage += timeRatio * occupancy; 106 usedThirdBuffer = usedThirdBuffer || (occupancy > 1); 107 } 108 mSegmentHistory.push_front({mPendingSegment.totalTime, 109 mPendingSegment.numFrames, occupancyAverage, usedThirdBuffer}); 110 if (mSegmentHistory.size() > MAX_HISTORY_SIZE) { 111 mSegmentHistory.pop_back(); 112 } 113 } 114 mPendingSegment.clear(); 115 } 116 117 } // namespace android 118