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