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 #include "CameraUsageStats.h"
18
19 #include <statslog.h>
20
21 #include <android-base/logging.h>
22
23 namespace {
24
25 // Length of frame roundtrip history
26 const int kMaxHistoryLength = 100;
27
28 }
29
30 namespace android {
31 namespace automotive {
32 namespace evs {
33 namespace V1_1 {
34 namespace implementation {
35
36 using ::android::base::Result;
37 using ::android::base::StringAppendF;
38 using ::android::hardware::hidl_vec;
39 using ::android::hardware::automotive::evs::V1_1::BufferDesc;
40
updateFrameStatsOnArrival(const hidl_vec<BufferDesc> & bufs)41 void CameraUsageStats::updateFrameStatsOnArrival(
42 const hidl_vec<BufferDesc>& bufs) {
43 const auto now = android::uptimeMillis();
44 for (const auto& b : bufs) {
45 auto it = mBufferHistory.find(b.bufferId);
46 if (it == mBufferHistory.end()) {
47 mBufferHistory.emplace(b.bufferId, now);
48 } else {
49 it->second.timestamp = now;
50 }
51 }
52 }
53
54
updateFrameStatsOnReturn(const hidl_vec<BufferDesc> & bufs)55 void CameraUsageStats::updateFrameStatsOnReturn(
56 const hidl_vec<BufferDesc>& bufs) {
57 const auto now = android::uptimeMillis();
58 for (auto& b : bufs) {
59 auto it = mBufferHistory.find(b.bufferId);
60 if (it == mBufferHistory.end()) {
61 LOG(WARNING) << "Buffer " << b.bufferId << " from "
62 << b.deviceId << " is unknown.";
63 } else {
64 const auto roundtrip = now - it->second.timestamp;
65 it->second.history.emplace(roundtrip);
66 it->second.sum += roundtrip;
67 if (it->second.history.size() > kMaxHistoryLength) {
68 it->second.sum -= it->second.history.front();
69 it->second.history.pop();
70 }
71
72 if (roundtrip > it->second.peak) {
73 it->second.peak = roundtrip;
74 }
75
76 if (mStats.framesFirstRoundtripLatency == 0) {
77 mStats.framesFirstRoundtripLatency = roundtrip;
78 }
79 }
80 }
81 }
82
83
framesReceived(int n)84 void CameraUsageStats::framesReceived(int n) {
85 AutoMutex lock(mMutex);
86 mStats.framesReceived += n;
87 }
88
89
framesReceived(const hidl_vec<BufferDesc> & bufs)90 void CameraUsageStats::framesReceived(
91 const hidl_vec<BufferDesc>& bufs) {
92 AutoMutex lock(mMutex);
93 mStats.framesReceived += bufs.size();
94
95 updateFrameStatsOnArrival(bufs);
96 }
97
98
framesReturned(int n)99 void CameraUsageStats::framesReturned(int n) {
100 AutoMutex lock(mMutex);
101 mStats.framesReturned += n;
102 }
103
104
framesReturned(const hidl_vec<BufferDesc> & bufs)105 void CameraUsageStats::framesReturned(
106 const hidl_vec<BufferDesc>& bufs) {
107 AutoMutex lock(mMutex);
108 mStats.framesReturned += bufs.size();
109
110 updateFrameStatsOnReturn(bufs);
111 }
112
113
framesIgnored(int n)114 void CameraUsageStats::framesIgnored(int n) {
115 AutoMutex lock(mMutex);
116 mStats.framesIgnored += n;
117 }
118
119
framesSkippedToSync(int n)120 void CameraUsageStats::framesSkippedToSync(int n) {
121 AutoMutex lock(mMutex);
122 mStats.framesSkippedToSync += n;
123 }
124
125
eventsReceived()126 void CameraUsageStats::eventsReceived() {
127 AutoMutex lock(mMutex);
128 ++mStats.erroneousEventsCount;
129 }
130
131
updateNumClients(size_t n)132 void CameraUsageStats::updateNumClients(size_t n) {
133 AutoMutex lock(mMutex);
134 if (n > mStats.peakClientsCount) {
135 mStats.peakClientsCount = n;
136 }
137 }
138
139
getTimeCreated() const140 int64_t CameraUsageStats::getTimeCreated() const {
141 AutoMutex lock(mMutex);
142 return mTimeCreatedMs;
143 }
144
145
getFramesReceived() const146 int64_t CameraUsageStats::getFramesReceived() const {
147 AutoMutex lock(mMutex);
148 return mStats.framesReceived;
149 }
150
151
getFramesReturned() const152 int64_t CameraUsageStats::getFramesReturned() const {
153 AutoMutex lock(mMutex);
154 return mStats.framesReturned;
155 }
156
157
snapshot()158 CameraUsageStatsRecord CameraUsageStats::snapshot() {
159 AutoMutex lock(mMutex);
160
161 int32_t sum = 0;
162 int32_t peak = 0;
163 int32_t len = 0;
164 for (auto& [id, rec] : mBufferHistory) {
165 sum += rec.sum;
166 len += rec.history.size();
167 if (peak < rec.peak) {
168 peak = rec.peak;
169 }
170 }
171
172 mStats.framesPeakRoundtripLatency = peak;
173 mStats.framesAvgRoundtripLatency = (double)sum / len;
174 return mStats;
175 }
176
177
writeStats() const178 Result<void> CameraUsageStats::writeStats() const {
179 AutoMutex lock(mMutex);
180
181 // Reports the usage statistics before the destruction
182 // EvsUsageStatsReported atom is defined in
183 // frameworks/base/cmds/statsd/src/atoms.proto
184 const auto duration = android::uptimeMillis() - mTimeCreatedMs;
185 android::util::stats_write(android::util::EVS_USAGE_STATS_REPORTED,
186 mId,
187 mStats.peakClientsCount,
188 mStats.erroneousEventsCount,
189 mStats.framesFirstRoundtripLatency,
190 mStats.framesAvgRoundtripLatency,
191 mStats.framesPeakRoundtripLatency,
192 mStats.framesReceived,
193 mStats.framesIgnored,
194 mStats.framesSkippedToSync,
195 duration);
196 return {};
197 }
198
199
toString(const CameraUsageStatsRecord & record,const char * indent)200 std::string CameraUsageStats::toString(const CameraUsageStatsRecord& record, const char* indent) {
201 return record.toString(indent);
202 }
203
204 } // namespace implementation
205 } // namespace V1_1
206 } // namespace evs
207 } // namespace automotive
208 } // namespace android
209
210