xref: /aosp_15_r20/frameworks/native/libs/gui/OccupancyTracker.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2016 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
18*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "OccupancyTracker"
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker #include <gui/OccupancyTracker.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <binder/Parcel.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker namespace android {
28*38e8c45fSAndroid Build Coastguard Worker 
writeToParcel(Parcel * parcel) const29*38e8c45fSAndroid Build Coastguard Worker status_t OccupancyTracker::Segment::writeToParcel(Parcel* parcel) const {
30*38e8c45fSAndroid Build Coastguard Worker     status_t result = parcel->writeInt64(totalTime);
31*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
32*38e8c45fSAndroid Build Coastguard Worker         return result;
33*38e8c45fSAndroid Build Coastguard Worker     }
34*38e8c45fSAndroid Build Coastguard Worker     result = parcel->writeUint64(static_cast<uint64_t>(numFrames));
35*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
36*38e8c45fSAndroid Build Coastguard Worker         return result;
37*38e8c45fSAndroid Build Coastguard Worker     }
38*38e8c45fSAndroid Build Coastguard Worker     result = parcel->writeFloat(occupancyAverage);
39*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
40*38e8c45fSAndroid Build Coastguard Worker         return result;
41*38e8c45fSAndroid Build Coastguard Worker     }
42*38e8c45fSAndroid Build Coastguard Worker     return parcel->writeBool(usedThirdBuffer);
43*38e8c45fSAndroid Build Coastguard Worker }
44*38e8c45fSAndroid Build Coastguard Worker 
readFromParcel(const Parcel * parcel)45*38e8c45fSAndroid Build Coastguard Worker status_t OccupancyTracker::Segment::readFromParcel(const Parcel* parcel) {
46*38e8c45fSAndroid Build Coastguard Worker     status_t result = parcel->readInt64(&totalTime);
47*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
48*38e8c45fSAndroid Build Coastguard Worker         return result;
49*38e8c45fSAndroid Build Coastguard Worker     }
50*38e8c45fSAndroid Build Coastguard Worker     uint64_t uintNumFrames = 0;
51*38e8c45fSAndroid Build Coastguard Worker     result = parcel->readUint64(&uintNumFrames);
52*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
53*38e8c45fSAndroid Build Coastguard Worker         return result;
54*38e8c45fSAndroid Build Coastguard Worker     }
55*38e8c45fSAndroid Build Coastguard Worker     numFrames = static_cast<size_t>(uintNumFrames);
56*38e8c45fSAndroid Build Coastguard Worker     result = parcel->readFloat(&occupancyAverage);
57*38e8c45fSAndroid Build Coastguard Worker     if (result != OK) {
58*38e8c45fSAndroid Build Coastguard Worker         return result;
59*38e8c45fSAndroid Build Coastguard Worker     }
60*38e8c45fSAndroid Build Coastguard Worker     return parcel->readBool(&usedThirdBuffer);
61*38e8c45fSAndroid Build Coastguard Worker }
62*38e8c45fSAndroid Build Coastguard Worker 
registerOccupancyChange(size_t occupancy)63*38e8c45fSAndroid Build Coastguard Worker void OccupancyTracker::registerOccupancyChange(size_t occupancy) {
64*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
65*38e8c45fSAndroid Build Coastguard Worker     nsecs_t now = systemTime();
66*38e8c45fSAndroid Build Coastguard Worker     nsecs_t delta = now - mLastOccupancyChangeTime;
67*38e8c45fSAndroid Build Coastguard Worker     if (delta > NEW_SEGMENT_DELAY) {
68*38e8c45fSAndroid Build Coastguard Worker         recordPendingSegment();
69*38e8c45fSAndroid Build Coastguard Worker     } else {
70*38e8c45fSAndroid Build Coastguard Worker         mPendingSegment.totalTime += delta;
71*38e8c45fSAndroid Build Coastguard Worker         if (mPendingSegment.mOccupancyTimes.count(mLastOccupancy)) {
72*38e8c45fSAndroid Build Coastguard Worker             mPendingSegment.mOccupancyTimes[mLastOccupancy] += delta;
73*38e8c45fSAndroid Build Coastguard Worker         } else {
74*38e8c45fSAndroid Build Coastguard Worker             mPendingSegment.mOccupancyTimes[mLastOccupancy] = delta;
75*38e8c45fSAndroid Build Coastguard Worker         }
76*38e8c45fSAndroid Build Coastguard Worker     }
77*38e8c45fSAndroid Build Coastguard Worker     if (occupancy > mLastOccupancy) {
78*38e8c45fSAndroid Build Coastguard Worker         ++mPendingSegment.numFrames;
79*38e8c45fSAndroid Build Coastguard Worker     }
80*38e8c45fSAndroid Build Coastguard Worker     mLastOccupancyChangeTime = now;
81*38e8c45fSAndroid Build Coastguard Worker     mLastOccupancy = occupancy;
82*38e8c45fSAndroid Build Coastguard Worker }
83*38e8c45fSAndroid Build Coastguard Worker 
getSegmentHistory(bool forceFlush)84*38e8c45fSAndroid Build Coastguard Worker std::vector<OccupancyTracker::Segment> OccupancyTracker::getSegmentHistory(
85*38e8c45fSAndroid Build Coastguard Worker         bool forceFlush) {
86*38e8c45fSAndroid Build Coastguard Worker     if (forceFlush) {
87*38e8c45fSAndroid Build Coastguard Worker         recordPendingSegment();
88*38e8c45fSAndroid Build Coastguard Worker     }
89*38e8c45fSAndroid Build Coastguard Worker     std::vector<Segment> segments(mSegmentHistory.cbegin(),
90*38e8c45fSAndroid Build Coastguard Worker             mSegmentHistory.cend());
91*38e8c45fSAndroid Build Coastguard Worker     mSegmentHistory.clear();
92*38e8c45fSAndroid Build Coastguard Worker     return segments;
93*38e8c45fSAndroid Build Coastguard Worker }
94*38e8c45fSAndroid Build Coastguard Worker 
recordPendingSegment()95*38e8c45fSAndroid Build Coastguard Worker void OccupancyTracker::recordPendingSegment() {
96*38e8c45fSAndroid Build Coastguard Worker     // Only record longer segments to get a better measurement of actual double-
97*38e8c45fSAndroid Build Coastguard Worker     // vs. triple-buffered time
98*38e8c45fSAndroid Build Coastguard Worker     if (mPendingSegment.numFrames > LONG_SEGMENT_THRESHOLD) {
99*38e8c45fSAndroid Build Coastguard Worker         float occupancyAverage = 0.0f;
100*38e8c45fSAndroid Build Coastguard Worker         bool usedThirdBuffer = false;
101*38e8c45fSAndroid Build Coastguard Worker         for (const auto& timePair : mPendingSegment.mOccupancyTimes) {
102*38e8c45fSAndroid Build Coastguard Worker             size_t occupancy = timePair.first;
103*38e8c45fSAndroid Build Coastguard Worker             float timeRatio = static_cast<float>(timePair.second) /
104*38e8c45fSAndroid Build Coastguard Worker                     mPendingSegment.totalTime;
105*38e8c45fSAndroid Build Coastguard Worker             occupancyAverage += timeRatio * occupancy;
106*38e8c45fSAndroid Build Coastguard Worker             usedThirdBuffer = usedThirdBuffer || (occupancy > 1);
107*38e8c45fSAndroid Build Coastguard Worker         }
108*38e8c45fSAndroid Build Coastguard Worker         mSegmentHistory.push_front({mPendingSegment.totalTime,
109*38e8c45fSAndroid Build Coastguard Worker                 mPendingSegment.numFrames, occupancyAverage, usedThirdBuffer});
110*38e8c45fSAndroid Build Coastguard Worker         if (mSegmentHistory.size() > MAX_HISTORY_SIZE) {
111*38e8c45fSAndroid Build Coastguard Worker             mSegmentHistory.pop_back();
112*38e8c45fSAndroid Build Coastguard Worker         }
113*38e8c45fSAndroid Build Coastguard Worker     }
114*38e8c45fSAndroid Build Coastguard Worker     mPendingSegment.clear();
115*38e8c45fSAndroid Build Coastguard Worker }
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker } // namespace android
118