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 <queue>
21 #include <unordered_map>
22 
23 #include <inttypes.h>
24 
25 #include <android/hardware/automotive/evs/1.1/types.h>
26 #include <android-base/result.h>
27 #include <android-base/stringprintf.h>
28 #include <utils/Mutex.h>
29 #include <utils/RefBase.h>
30 #include <utils/SystemClock.h>
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),
102                 indent, framesReceived,
103                 indent, framesReturned,
104                 indent, framesIgnored,
105                 indent, framesSkippedToSync,
106                 indent, framesFirstRoundtripLatency,
107                 indent, framesPeakRoundtripLatency,
108                 indent, framesAvgRoundtripLatency,
109                 indent, peakClientsCount);
110 
111         return buffer;
112     }
113 };
114 
115 
116 struct BufferRecord {
BufferRecordBufferRecord117     BufferRecord(int64_t timestamp) :
118         timestamp(timestamp),
119         sum(0),
120         peak(0) {}
121 
122     // Recent processing time
123     std::queue<int32_t> history;
124 
125     // Timestamp on the buffer arrival
126     int64_t timestamp;
127 
128     // Sum of processing times
129     int64_t sum;
130 
131     // Peak processing time
132     int64_t peak;
133 };
134 
135 
136 class CameraUsageStats : public RefBase {
137 public:
CameraUsageStats(int32_t id)138     CameraUsageStats(int32_t id)
139         : mMutex(Mutex()),
140           mId(id),
141           mTimeCreatedMs(android::uptimeMillis()),
142           mStats({}) {}
143 
144 private:
145     // Mutex to protect a collection record
146     mutable Mutex mMutex;
147 
148     // Unique identifier
149     int32_t mId;
150 
151     // Time this object was created
152     int64_t mTimeCreatedMs;
153 
154     // Usage statistics to collect
155     CameraUsageStatsRecord mStats GUARDED_BY(mMutex);
156 
157     // Frame buffer histories
158     std::unordered_map<int, BufferRecord> mBufferHistory GUARDED_BY(mMutex);
159 
160 public:
161     void framesReceived(int n = 1) EXCLUDES(mMutex);
162     void framesReturned(int n = 1) EXCLUDES(mMutex);
163     void framesReceived(
164             const hardware::hidl_vec<::android::hardware::automotive::evs::V1_1::BufferDesc>& bufs
165         ) EXCLUDES(mMutex);
166     void framesReturned(
167             const hardware::hidl_vec<::android::hardware::automotive::evs::V1_1::BufferDesc>& bufs
168         ) EXCLUDES(mMutex);
169     void framesIgnored(int n = 1) EXCLUDES(mMutex);
170     void framesSkippedToSync(int n = 1) EXCLUDES(mMutex);
171     void eventsReceived() EXCLUDES(mMutex);
172     int64_t getTimeCreated() const EXCLUDES(mMutex);
173     int64_t getFramesReceived() const EXCLUDES(mMutex);
174     int64_t getFramesReturned() const EXCLUDES(mMutex);
175     void updateNumClients(size_t n) EXCLUDES(mMutex);
176     void updateFrameStatsOnArrival(
177             const hardware::hidl_vec<::android::hardware::automotive::evs::V1_1::BufferDesc>& bufs
178         ) REQUIRES(mMutex);
179     void updateFrameStatsOnReturn(
180             const hardware::hidl_vec<::android::hardware::automotive::evs::V1_1::BufferDesc>& bufs
181         ) REQUIRES(mMutex);
182 
183     // Returns the statistics collected so far
184     CameraUsageStatsRecord snapshot() EXCLUDES(mMutex);
185 
186     // Reports the usage statistics
187     android::base::Result<void> writeStats() const EXCLUDES(mMutex);
188 
189     // Generates a string with current statistics
190     static std::string toString(const CameraUsageStatsRecord& record, const char* indent = "");
191 };
192 
193 
194 } // namespace implementation
195 } // namespace V1_1
196 } // namespace evs
197 } // namespace automotive
198 } // namespace android
199 
200 #endif // ANDROID_AUTOMOTIVE_EVS_V1_1_CAMERAUSAGESTATS_H
201