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