1 /*
2  * Copyright (C) 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_SERVICE_UTILS_SESSION_STATS_BUILDER_H
18 #define ANDROID_SERVICE_UTILS_SESSION_STATS_BUILDER_H
19 
20 #include <utils/Errors.h>
21 
22 #include <array>
23 #include <map>
24 #include <mutex>
25 #include <unordered_map>
26 #include <utility>
27 
28 namespace android {
29 
30 // Helper class to build stream stats
31 struct StreamStats {
32     // Fields for buffer drop
33     int64_t mRequestedFrameCount;
34     int64_t mDroppedFrameCount;
35     bool mCounterStopped;
36 
37     // Fields for stream startup latency
38     int32_t mStartLatencyMs;
39 
40     // Fields for capture latency measurement
41     const static int LATENCY_BIN_COUNT = 10;
42     // Boundary values separating between adjacent bins, excluding 0 and
43     // infinity.
44     const static std::array<int32_t, LATENCY_BIN_COUNT-1> mCaptureLatencyBins;
45     // Counter values for all histogram bins. One more entry than mCaptureLatencyBins.
46     std::array<int64_t, LATENCY_BIN_COUNT> mCaptureLatencyHistogram;
47 
StreamStatsStreamStats48     StreamStats() : mRequestedFrameCount(0),
49                      mDroppedFrameCount(0),
50                      mCounterStopped(false),
51                      mStartLatencyMs(0),
52                      mCaptureLatencyHistogram{}
53                   {}
54 
55     void updateLatencyHistogram(int32_t latencyMs);
56 };
57 
58 // Helper class to build session stats
59 class SessionStatsBuilder {
60 public:
61 
62     status_t addStream(int streamId);
63     status_t removeStream(int streamId);
64 
65     // Return the session statistics and reset the internal states.
66     void buildAndReset(/*out*/int64_t* requestCount,
67             /*out*/int64_t* errorResultCount,
68             /*out*/bool* deviceError,
69             /*out*/std::pair<int32_t, int32_t>* mostRequestedFpsRange,
70             /*out*/std::map<int, StreamStats>* statsMap);
71 
72     // Stream specific counter
73     void startCounter(int streamId);
74     void stopCounter(int streamId);
75     void incCounter(int streamId, bool dropped, int32_t captureLatencyMs);
76 
77     // Session specific counter
78     void stopCounter();
79     void incResultCounter(bool dropped);
80     void onDeviceError();
81 
82     // Session specific statistics
83 
84     // Limit on size of FPS range histogram
85     static const size_t FPS_HISTOGRAM_MAX_SIZE = 10;
86 
87     void incFpsRequestedCount(int32_t minFps, int32_t maxFps, int64_t frameNumber);
88 
SessionStatsBuilder()89     SessionStatsBuilder() : mRequestCount(0), mErrorResultCount(0),
90              mCounterStopped(false), mDeviceError(false) {}
91 private:
92     std::mutex mLock;
93     int64_t mRequestCount;
94     int64_t mErrorResultCount;
95     bool mCounterStopped;
96     bool mDeviceError;
97     std::string mUserTag;
98 
99     // Histogram of frame counts of requested target FPS ranges
100     // (min_fps << 32 | max_fps) -> (# of frames with this fps, last seen framenumber)
101     std::unordered_map<uint64_t, std::pair<int64_t, int64_t>> mRequestedFpsRangeHistogram;
102 
103     // Map from stream id to stream statistics
104     std::map<int, StreamStats> mStatsMap;
105 };
106 
107 }; // namespace android
108 
109 #endif // ANDROID_SERVICE_UTILS_SESSION_STATS_BUILDER_H
110