| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "CameraUsageStats.h" |
| |
| #include <android-base/logging.h> |
| |
| #include <statslog_evs.h> |
| |
| namespace { |
| |
| // Length of frame roundtrip history |
| const int kMaxHistoryLength = 100; |
| |
| } // namespace |
| |
| namespace android { |
| namespace automotive { |
| namespace evs { |
| namespace V1_1 { |
| namespace implementation { |
| |
| using ::android::base::Result; |
| using ::android::base::StringAppendF; |
| using ::android::hardware::hidl_vec; |
| using ::android::hardware::automotive::evs::V1_1::BufferDesc; |
| |
| void CameraUsageStats::updateFrameStatsOnArrival(const hidl_vec<BufferDesc>& bufs) { |
| const auto now = android::uptimeMillis(); |
| for (const auto& b : bufs) { |
| auto it = mBufferHistory.find(b.bufferId); |
| if (it == mBufferHistory.end()) { |
| mBufferHistory.emplace(b.bufferId, now); |
| } else { |
| it->second.timestamp = now; |
| } |
| } |
| } |
| |
| void CameraUsageStats::updateFrameStatsOnReturn(const hidl_vec<BufferDesc>& bufs) { |
| const auto now = android::uptimeMillis(); |
| for (auto& b : bufs) { |
| auto it = mBufferHistory.find(b.bufferId); |
| if (it == mBufferHistory.end()) { |
| LOG(WARNING) << "Buffer " << b.bufferId << " from " << b.deviceId << " is unknown."; |
| } else { |
| const auto roundtrip = now - it->second.timestamp; |
| it->second.history.emplace(roundtrip); |
| it->second.sum += roundtrip; |
| if (it->second.history.size() > kMaxHistoryLength) { |
| it->second.sum -= it->second.history.front(); |
| it->second.history.pop(); |
| } |
| |
| if (roundtrip > it->second.peak) { |
| it->second.peak = roundtrip; |
| } |
| |
| if (mStats.framesFirstRoundtripLatency == 0) { |
| mStats.framesFirstRoundtripLatency = roundtrip; |
| } |
| } |
| } |
| } |
| |
| void CameraUsageStats::framesReceived(int n) { |
| AutoMutex lock(mMutex); |
| mStats.framesReceived += n; |
| } |
| |
| void CameraUsageStats::framesReceived(const hidl_vec<BufferDesc>& bufs) { |
| AutoMutex lock(mMutex); |
| mStats.framesReceived += bufs.size(); |
| |
| updateFrameStatsOnArrival(bufs); |
| } |
| |
| void CameraUsageStats::framesReturned(int n) { |
| AutoMutex lock(mMutex); |
| mStats.framesReturned += n; |
| } |
| |
| void CameraUsageStats::framesReturned(const hidl_vec<BufferDesc>& bufs) { |
| AutoMutex lock(mMutex); |
| mStats.framesReturned += bufs.size(); |
| |
| updateFrameStatsOnReturn(bufs); |
| } |
| |
| void CameraUsageStats::framesIgnored(int n) { |
| AutoMutex lock(mMutex); |
| mStats.framesIgnored += n; |
| } |
| |
| void CameraUsageStats::framesSkippedToSync(int n) { |
| AutoMutex lock(mMutex); |
| mStats.framesSkippedToSync += n; |
| } |
| |
| void CameraUsageStats::eventsReceived() { |
| AutoMutex lock(mMutex); |
| ++mStats.erroneousEventsCount; |
| } |
| |
| void CameraUsageStats::updateNumClients(size_t n) { |
| AutoMutex lock(mMutex); |
| if (n > mStats.peakClientsCount) { |
| mStats.peakClientsCount = n; |
| } |
| } |
| |
| int64_t CameraUsageStats::getTimeCreated() const { |
| AutoMutex lock(mMutex); |
| return mTimeCreatedMs; |
| } |
| |
| int64_t CameraUsageStats::getFramesReceived() const { |
| AutoMutex lock(mMutex); |
| return mStats.framesReceived; |
| } |
| |
| int64_t CameraUsageStats::getFramesReturned() const { |
| AutoMutex lock(mMutex); |
| return mStats.framesReturned; |
| } |
| |
| CameraUsageStatsRecord CameraUsageStats::snapshot() { |
| AutoMutex lock(mMutex); |
| |
| int32_t sum = 0; |
| int32_t peak = 0; |
| int32_t len = 0; |
| for (auto& [id, rec] : mBufferHistory) { |
| sum += rec.sum; |
| len += rec.history.size(); |
| if (peak < rec.peak) { |
| peak = rec.peak; |
| } |
| } |
| |
| mStats.framesPeakRoundtripLatency = peak; |
| mStats.framesAvgRoundtripLatency = (double)sum / len; |
| return mStats; |
| } |
| |
| Result<void> CameraUsageStats::writeStats() const { |
| AutoMutex lock(mMutex); |
| |
| // EvsUsageStatsReported atom is defined in |
| // frameworks/base/cmds/statsd/src/atoms.proto |
| const auto duration = android::uptimeMillis() - mTimeCreatedMs; |
| auto result = |
| stats::stats_write(stats::EVS_USAGE_STATS_REPORTED, mId, mStats.peakClientsCount, |
| mStats.erroneousEventsCount, mStats.framesFirstRoundtripLatency, |
| mStats.framesAvgRoundtripLatency, mStats.framesPeakRoundtripLatency, |
| mStats.framesReceived, mStats.framesIgnored, |
| mStats.framesSkippedToSync, duration); |
| if (result < 0) { |
| LOG(WARNING) << "Failed to report usage stats"; |
| } |
| return {}; |
| } |
| |
| std::string CameraUsageStats::toString(const CameraUsageStatsRecord& record, const char* indent) { |
| return record.toString(indent); |
| } |
| |
| } // namespace implementation |
| } // namespace V1_1 |
| } // namespace evs |
| } // namespace automotive |
| } // namespace android |