1 /*
2  * Copyright 2022 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 #ifndef CPP_EVS_MANAGER_AIDL_STATS_INCLUDE_CAMERAUSAGESTATS_H
18 #define CPP_EVS_MANAGER_AIDL_STATS_INCLUDE_CAMERAUSAGESTATS_H
19 
20 #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
21 #include <android-base/stringprintf.h>
22 #include <utils/Mutex.h>
23 #include <utils/RefBase.h>
24 #include <utils/SystemClock.h>
25 
26 #include <cinttypes>
27 #include <queue>
28 #include <unordered_map>
29 
30 namespace aidl::android::automotive::evs::implementation {
31 
32 namespace aidlevs = ::aidl::android::hardware::automotive::evs;
33 
34 struct CameraUsageStatsRecord {
35 public:
36     // Time a snapshot is generated
37     nsecs_t timestamp;
38 
39     // Total number of frames received
40     int64_t framesReceived;
41 
42     // Total number of frames returned to EVS HAL
43     int64_t framesReturned;
44 
45     // Number of frames ignored because no clients are listening
46     int64_t framesIgnored;
47 
48     // Number of frames skipped to synchronize camera frames
49     int64_t framesSkippedToSync;
50 
51     // Roundtrip latency of the very first frame after the stream started.
52     int64_t framesFirstRoundtripLatency;
53 
54     // Peak mFrame roundtrip latency
55     int64_t framesPeakRoundtripLatency;
56 
57     // Average mFrame roundtrip latency
58     double framesAvgRoundtripLatency;
59 
60     // Number of the erroneous streaming events
61     int32_t erroneousEventsCount;
62 
63     // Peak number of active clients
64     int32_t peakClientsCount;
65 
66     // Calculates a delta between two records
67     CameraUsageStatsRecord& operator-=(const CameraUsageStatsRecord& rhs) {
68         // Only calculates differences in the frame statistics
69         framesReceived = framesReceived - rhs.framesReceived;
70         framesReturned = framesReturned - rhs.framesReturned;
71         framesIgnored = framesIgnored - rhs.framesIgnored;
72         framesSkippedToSync = framesSkippedToSync - rhs.framesSkippedToSync;
73         erroneousEventsCount = erroneousEventsCount - rhs.erroneousEventsCount;
74 
75         return *this;
76     }
77 
78     friend CameraUsageStatsRecord operator-(CameraUsageStatsRecord lhs,
79                                             const CameraUsageStatsRecord& rhs) noexcept {
80         lhs -= rhs;  // reuse compound assignment
81         return lhs;
82     }
83 
84     // Constructs a string that shows collected statistics
85     std::string toString(const char* indent = "") const {
86         std::string buffer;
87         ::android::base::StringAppendF(&buffer,
88                                        "%sTime Collected: @%" PRId64 "ms\n"
89                                        "%sFrames Received: %" PRId64 "\n"
90                                        "%sFrames Returned: %" PRId64 "\n"
91                                        "%sFrames Ignored : %" PRId64 "\n"
92                                        "%sFrames Skipped To Sync: %" PRId64 "\n"
93                                        "%sFrames First Roundtrip: %" PRId64 "\n"
94                                        "%sFrames Peak Roundtrip: %" PRId64 "\n"
95                                        "%sFrames Average Roundtrip: %f\n"
96                                        "%sPeak Number of Clients: %" PRId32 "\n\n",
97                                        indent, ns2ms(timestamp), indent, framesReceived, indent,
98                                        framesReturned, indent, framesIgnored, indent,
99                                        framesSkippedToSync, indent, framesFirstRoundtripLatency,
100                                        indent, framesPeakRoundtripLatency, indent,
101                                        framesAvgRoundtripLatency, indent, peakClientsCount);
102 
103         return buffer;
104     }
105 };
106 
107 struct BufferRecord {
BufferRecordBufferRecord108     BufferRecord(int64_t timestamp) : timestamp(timestamp), sum(0), peak(0) {}
109 
110     // Recent processing time
111     std::queue<int32_t> history;
112 
113     // Timestamp on the buffer arrival
114     int64_t timestamp;
115 
116     // Sum of processing times
117     int64_t sum;
118 
119     // Peak processing time
120     int64_t peak;
121 };
122 
123 class CameraUsageStats : public ::android::RefBase {
124 public:
CameraUsageStats(int32_t id)125     CameraUsageStats(int32_t id) :
126           mMutex(::android::Mutex()),
127           mId(id),
128           mTimeCreatedMs(::android::uptimeMillis()),
129           mStats({}) {}
130 
131     void framesReceived(int32_t n = 1) EXCLUDES(mMutex);
132     void framesReturned(int32_t n = 1) EXCLUDES(mMutex);
133     void framesReceived(const std::vector<aidlevs::BufferDesc>& bufs) EXCLUDES(mMutex);
134     void framesReturned(const std::vector<aidlevs::BufferDesc>& bufs) EXCLUDES(mMutex);
135     void framesIgnored(int32_t n = 1) EXCLUDES(mMutex);
136     void framesSkippedToSync(int32_t n = 1) EXCLUDES(mMutex);
137     void eventsReceived() EXCLUDES(mMutex);
138     int64_t getTimeCreated() const EXCLUDES(mMutex);
139     int64_t getFramesReceived() const EXCLUDES(mMutex);
140     int64_t getFramesReturned() const EXCLUDES(mMutex);
141     void updateNumClients(size_t n) EXCLUDES(mMutex);
142     void updateFrameStatsOnArrivalLocked(const std::vector<aidlevs::BufferDesc>& bufs)
143             REQUIRES(mMutex);
144     void updateFrameStatsOnReturnLocked(const std::vector<aidlevs::BufferDesc>& bufs)
145             REQUIRES(mMutex);
146 
147     // Returns the statistics collected so far
148     CameraUsageStatsRecord snapshot() EXCLUDES(mMutex);
149 
150     // Reports the usage statistics
151     void writeStats() const EXCLUDES(mMutex);
152 
153     // Generates a string with current statistics
154     static std::string toString(const CameraUsageStatsRecord& record, const char* indent = "");
155 
156 private:
157     // Mutex to protect a collection record
158     mutable ::android::Mutex mMutex;
159 
160     // Unique identifier
161     int32_t mId;
162 
163     // Time this object was created
164     int64_t mTimeCreatedMs;
165 
166     // Usage statistics to collect
167     CameraUsageStatsRecord mStats GUARDED_BY(mMutex);
168 
169     // Frame buffer histories
170     std::unordered_map<int, BufferRecord> mBufferHistory GUARDED_BY(mMutex);
171 };
172 
173 }  // namespace aidl::android::automotive::evs::implementation
174 
175 #endif  // CPP_EVS_MANAGER_AIDL_STATS_INCLUDE_CAMERAUSAGESTATS_H
176