blob: 700fbaa855fa56a919ff490953b6e1271af90c47 [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>
Andy Hung224f82f2022-03-22 00:00:49 -070022#include <vector>
Andy Hungc747c532022-03-07 21:41:14 -080023
24#include <android-base/thread_annotations.h>
25#include <audio_utils/Statistics.h>
26
27namespace android::mediautils {
28
29/**
30 * MethodStatistics is used to associate Binder codes
31 * with a method name and execution time statistics.
32 *
33 * This is used to track binder transaction times for
34 * AudioFlinger and AudioPolicy services.
35 *
36 * Here, Code is the enumeration type for the method
37 * lookup.
38 */
39template <typename Code>
40class MethodStatistics {
41public:
42 using FloatType = float;
43 using StatsType = audio_utils::Statistics<FloatType>;
44
45 /**
46 * Method statistics.
47 *
48 * Initialized with the Binder transaction list for tracking AudioFlinger
49 * and AudioPolicyManager execution statistics.
50 */
51 explicit MethodStatistics(
52 const std::initializer_list<std::pair<const Code, std::string>>& methodMap = {})
53 : mMethodMap{methodMap} {}
54
55 /**
56 * Adds a method event, typically execution time in ms.
57 */
58 void event(Code code, FloatType executeMs) {
59 std::lock_guard lg(mLock);
60 mStatisticsMap[code].add(executeMs);
61 }
62
63 /**
64 * Returns the name for the method code.
65 */
66 std::string getMethodForCode(Code code) const {
67 auto it = mMethodMap.find(code);
68 return it == mMethodMap.end() ? std::to_string((int)code) : it->second;
69 }
70
71 /**
72 * Returns the number of times the method was invoked by event().
73 */
74 size_t getMethodCount(Code code) const {
75 std::lock_guard lg(mLock);
76 auto it = mStatisticsMap.find(code);
77 return it == mStatisticsMap.end() ? 0 : it->second.getN();
78 }
79
80 /**
81 * Returns the statistics object for the method.
82 */
83 StatsType getStatistics(Code code) const {
84 std::lock_guard lg(mLock);
85 auto it = mStatisticsMap.find(code);
86 return it == mStatisticsMap.end() ? StatsType{} : it->second;
87 }
88
89 /**
90 * Dumps the current method statistics.
91 */
92 std::string dump() const {
93 std::stringstream ss;
94 std::lock_guard lg(mLock);
Andy Hung224f82f2022-03-22 00:00:49 -070095 if constexpr (std::is_same_v<Code, std::string>) {
96 for (const auto &[code, stats] : mStatisticsMap) {
97 ss << code <<
98 " n=" << stats.getN() << " " << stats.toString() << "\n";
99 }
100 } else /* constexpr */ {
101 for (const auto &[code, stats] : mStatisticsMap) {
102 ss << int(code) << " " << getMethodForCode(code) <<
103 " n=" << stats.getN() << " " << stats.toString() << "\n";
104 }
Andy Hungc747c532022-03-07 21:41:14 -0800105 }
106 return ss.str();
107 }
108
109private:
110 const std::map<Code, std::string> mMethodMap;
111 mutable std::mutex mLock;
112 std::map<Code, StatsType> mStatisticsMap GUARDED_BY(mLock);
113};
114
Andy Hung224f82f2022-03-22 00:00:49 -0700115// Managed Statistics support.
116// Supported Modules
117#define METHOD_STATISTICS_MODULE_NAME_AUDIO_HIDL "AudioHidl"
118
119// Returns a vector of class names for the module, or a nullptr if module not found.
120std::shared_ptr<std::vector<std::string>>
121getStatisticsClassesForModule(std::string_view moduleName);
122
123// Returns a statistics object for that class, or a nullptr if class not found.
124std::shared_ptr<MethodStatistics<std::string>>
125getStatisticsForClass(std::string_view className);
126
Andy Hungc747c532022-03-07 21:41:14 -0800127// Only if used, requires IBinder.h to be included at the location of invocation.
128#define METHOD_STATISTICS_BINDER_CODE_NAMES(CODE_TYPE) \
129 {(CODE_TYPE)IBinder::PING_TRANSACTION , "ping"}, \
130 {(CODE_TYPE)IBinder::DUMP_TRANSACTION , "dump"}, \
131 {(CODE_TYPE)IBinder::SHELL_COMMAND_TRANSACTION , "shellCommand"}, \
132 {(CODE_TYPE)IBinder::INTERFACE_TRANSACTION , "getInterfaceDescriptor"}, \
133 {(CODE_TYPE)IBinder::SYSPROPS_TRANSACTION , "SYSPROPS_TRANSACTION"}, \
134 {(CODE_TYPE)IBinder::EXTENSION_TRANSACTION , "EXTENSION_TRANSACTION"}, \
135 {(CODE_TYPE)IBinder::DEBUG_PID_TRANSACTION , "DEBUG_PID_TRANSACTION"}, \
136
137} // android::mediautils