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 
18 #ifndef ANDROID_GUI_OCCUPANCYTRACKER_H
19 #define ANDROID_GUI_OCCUPANCYTRACKER_H
20 
21 #include <binder/Parcelable.h>
22 
23 #include <utils/Timers.h>
24 
25 #include <deque>
26 #include <unordered_map>
27 
28 namespace android {
29 
30 class String8;
31 
32 class OccupancyTracker
33 {
34 public:
OccupancyTracker()35     OccupancyTracker()
36       : mPendingSegment(),
37         mSegmentHistory(),
38         mLastOccupancy(0),
39         mLastOccupancyChangeTime(0) {}
40 
41     struct Segment : public Parcelable {
SegmentSegment42         Segment()
43           : totalTime(0),
44             numFrames(0),
45             occupancyAverage(0.0f),
46             usedThirdBuffer(false) {}
47 
SegmentSegment48         Segment(nsecs_t _totalTime, size_t _numFrames, float _occupancyAverage,
49                 bool _usedThirdBuffer)
50           : totalTime(_totalTime),
51             numFrames(_numFrames),
52             occupancyAverage(_occupancyAverage),
53             usedThirdBuffer(_usedThirdBuffer) {}
54 
55         // Parcelable interface
56         virtual status_t writeToParcel(Parcel* parcel) const override;
57         virtual status_t readFromParcel(const Parcel* parcel) override;
58 
59         nsecs_t totalTime;
60         size_t numFrames;
61 
62         // Average occupancy of the queue over this segment. (0.0, 1.0) implies
63         // double-buffered, (1.0, 2.0) implies triple-buffered.
64         float occupancyAverage;
65 
66         // Whether a third buffer was used at all during this segment (since a
67         // segment could read as double-buffered on average, but still require a
68         // third buffer to avoid jank for some smaller portion)
69         bool usedThirdBuffer;
70     };
71 
72     void registerOccupancyChange(size_t occupancy);
73     std::vector<Segment> getSegmentHistory(bool forceFlush);
74 
75 private:
76     static constexpr size_t MAX_HISTORY_SIZE = 10;
77     static constexpr nsecs_t NEW_SEGMENT_DELAY = ms2ns(100);
78     static constexpr size_t LONG_SEGMENT_THRESHOLD = 3;
79 
80     struct PendingSegment {
clearPendingSegment81         void clear() {
82             totalTime = 0;
83             numFrames = 0;
84             mOccupancyTimes.clear();
85         }
86 
87         nsecs_t totalTime;
88         size_t numFrames;
89         std::unordered_map<size_t, nsecs_t> mOccupancyTimes;
90     };
91 
92     void recordPendingSegment();
93 
94     PendingSegment mPendingSegment;
95     std::deque<Segment> mSegmentHistory;
96 
97     size_t mLastOccupancy;
98     nsecs_t mLastOccupancyChangeTime;
99 
100 }; // class OccupancyTracker
101 
102 } // namespace android
103 
104 #endif
105