blob: 7d8061da0f825858b2d3cca5624b026808073230 [file] [log] [blame]
Andy Hungc747c532022-03-07 21:41:14 -08001/*
2 * Copyright (C) 2022 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#pragma once
18
19#include <map>
20#include <mutex>
21#include <string>
22
23#include <android-base/thread_annotations.h>
24#include <audio_utils/Statistics.h>
25
26namespace android::mediautils {
27
28/**
29 * MethodStatistics is used to associate Binder codes
30 * with a method name and execution time statistics.
31 *
32 * This is used to track binder transaction times for
33 * AudioFlinger and AudioPolicy services.
34 *
35 * Here, Code is the enumeration type for the method
36 * lookup.
37 */
38template <typename Code>
39class MethodStatistics {
40public:
41 using FloatType = float;
42 using StatsType = audio_utils::Statistics<FloatType>;
43
44 /**
45 * Method statistics.
46 *
47 * Initialized with the Binder transaction list for tracking AudioFlinger
48 * and AudioPolicyManager execution statistics.
49 */
50 explicit MethodStatistics(
51 const std::initializer_list<std::pair<const Code, std::string>>& methodMap = {})
52 : mMethodMap{methodMap} {}
53
54 /**
55 * Adds a method event, typically execution time in ms.
56 */
57 void event(Code code, FloatType executeMs) {
58 std::lock_guard lg(mLock);
59 mStatisticsMap[code].add(executeMs);
60 }
61
62 /**
63 * Returns the name for the method code.
64 */
65 std::string getMethodForCode(Code code) const {
66 auto it = mMethodMap.find(code);
67 return it == mMethodMap.end() ? std::to_string((int)code) : it->second;
68 }
69
70 /**
71 * Returns the number of times the method was invoked by event().
72 */
73 size_t getMethodCount(Code code) const {
74 std::lock_guard lg(mLock);
75 auto it = mStatisticsMap.find(code);
76 return it == mStatisticsMap.end() ? 0 : it->second.getN();
77 }
78
79 /**
80 * Returns the statistics object for the method.
81 */
82 StatsType getStatistics(Code code) const {
83 std::lock_guard lg(mLock);
84 auto it = mStatisticsMap.find(code);
85 return it == mStatisticsMap.end() ? StatsType{} : it->second;
86 }
87
88 /**
89 * Dumps the current method statistics.
90 */
91 std::string dump() const {
92 std::stringstream ss;
93 std::lock_guard lg(mLock);
94 for (const auto &[code, stats] : mStatisticsMap) {
95 ss << int(code) << " " << getMethodForCode(code) <<
96 " n=" << stats.getN() << " " << stats.toString() << "\n";
97 }
98 return ss.str();
99 }
100
101private:
102 const std::map<Code, std::string> mMethodMap;
103 mutable std::mutex mLock;
104 std::map<Code, StatsType> mStatisticsMap GUARDED_BY(mLock);
105};
106
107// Only if used, requires IBinder.h to be included at the location of invocation.
108#define METHOD_STATISTICS_BINDER_CODE_NAMES(CODE_TYPE) \
109 {(CODE_TYPE)IBinder::PING_TRANSACTION , "ping"}, \
110 {(CODE_TYPE)IBinder::DUMP_TRANSACTION , "dump"}, \
111 {(CODE_TYPE)IBinder::SHELL_COMMAND_TRANSACTION , "shellCommand"}, \
112 {(CODE_TYPE)IBinder::INTERFACE_TRANSACTION , "getInterfaceDescriptor"}, \
113 {(CODE_TYPE)IBinder::SYSPROPS_TRANSACTION , "SYSPROPS_TRANSACTION"}, \
114 {(CODE_TYPE)IBinder::EXTENSION_TRANSACTION , "EXTENSION_TRANSACTION"}, \
115 {(CODE_TYPE)IBinder::DEBUG_PID_TRANSACTION , "DEBUG_PID_TRANSACTION"}, \
116
117} // android::mediautils