1 /*
2  * Copyright (C) 2017 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 #pragma once
18 
19 #include "utils/Macros.h"
20 
21 #include <utils/Timers.h>
22 
23 #include <array>
24 #include <functional>
25 #include <tuple>
26 
27 namespace android {
28 namespace uirenderer {
29 
30 enum JankType {
31     kMissedVsync = 0,
32     kHighInputLatency,
33     kSlowUI,
34     kSlowSync,
35     kSlowRT,
36     kMissedDeadline,
37 
38     // must be last
39     NUM_BUCKETS,
40 };
41 
42 // For testing
43 class MockProfileData;
44 
45 // Try to keep as small as possible, should match ASHMEM_SIZE in
46 // GraphicsStatsService.java
47 class ProfileData {
48     PREVENT_COPY_AND_ASSIGN(ProfileData);
49 
50 public:
ProfileData()51     ProfileData() { reset(); }
52 
53     void reset();
54     void mergeWith(const ProfileData& other);
55     void dump(int fd) const;
56     uint32_t findPercentile(int percentile) const;
57 
58     void reportFrame(int64_t duration);
reportJank()59     void reportJank() { mJankFrameCount++; }
reportJankType(JankType type)60     void reportJankType(JankType type) { mJankTypeCounts[static_cast<int>(type)]++; }
61 
totalFrameCount()62     uint32_t totalFrameCount() const { return mTotalFrameCount; }
jankFrameCount()63     uint32_t jankFrameCount() const { return mJankFrameCount; }
statsStartTime()64     nsecs_t statsStartTime() const { return mStatStartTime; }
jankTypeCount(JankType type)65     uint32_t jankTypeCount(JankType type) const { return mJankTypeCounts[static_cast<int>(type)]; }
66 
67     struct HistogramEntry {
68         uint32_t renderTimeMs;
69         uint32_t frameCount;
70     };
71     void histogramForEach(const std::function<void(HistogramEntry)>& callback) const;
72 
HistogramSize()73     constexpr static int HistogramSize() {
74         return std::tuple_size<decltype(ProfileData::mFrameCounts)>::value +
75                std::tuple_size<decltype(ProfileData::mSlowFrameCounts)>::value;
76     }
77 
78     // Visible for testing
79     static uint32_t frameTimeForFrameCountIndex(uint32_t index);
80     static uint32_t frameTimeForSlowFrameCountIndex(uint32_t index);
81 
82 private:
83     // Open our guts up to unit tests
84     friend class MockProfileData;
85 
86     std::array<uint32_t, NUM_BUCKETS> mJankTypeCounts;
87     // See comments on kBucket* constants for what this holds
88     std::array<uint32_t, 57> mFrameCounts;
89     // Holds a histogram of frame times in 50ms increments from 150ms to 5s
90     std::array<uint16_t, 97> mSlowFrameCounts;
91 
92     uint32_t mTotalFrameCount;
93     uint32_t mJankFrameCount;
94     nsecs_t mStatStartTime;
95 };
96 
97 // For testing
98 class MockProfileData : public ProfileData {
99 public:
editJankTypeCounts()100     std::array<uint32_t, NUM_BUCKETS>& editJankTypeCounts() { return mJankTypeCounts; }
editFrameCounts()101     std::array<uint32_t, 57>& editFrameCounts() { return mFrameCounts; }
editSlowFrameCounts()102     std::array<uint16_t, 97>& editSlowFrameCounts() { return mSlowFrameCounts; }
editTotalFrameCount()103     uint32_t& editTotalFrameCount() { return mTotalFrameCount; }
editJankFrameCount()104     uint32_t& editJankFrameCount() { return mJankFrameCount; }
editStatStartTime()105     nsecs_t& editStatStartTime() { return mStatStartTime; }
106 };
107 
108 } /* namespace uirenderer */
109 } /* namespace android */
110