1 /*
2 * Copyright (C) 2021 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 #pragma once
17
18 #include <log/log.h>
19 #include <utils/Trace.h>
20
21 #include <algorithm>
22 #include <chrono>
23 #include <mutex>
24
25 #include "Hardware.h"
26 #include "StatsBase.h"
27 #include "Vibrator.h"
28
29 constexpr int32_t DURATION_BUCKET_WIDTH = 50;
30 constexpr int32_t DURATION_50MS_BUCKET_COUNT = 20;
31 constexpr int32_t DURATION_BUCKET_COUNT = DURATION_50MS_BUCKET_COUNT + 1;
32 constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
33
34 #ifndef ARRAY_SIZE
35 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
36 #endif
37
38 #ifdef HAPTIC_TRACE
39 static const char *kWaveformLookup[] = {"WAVEFORM_LONG_VIBRATION_EFFECT",
40 "WAVEFORM_RESERVED_1",
41 "WAVEFORM_CLICK",
42 "WAVEFORM_SHORT_VIBRATION_EFFECT",
43 "WAVEFORM_THUD",
44 "WAVEFORM_SPIN",
45 "WAVEFORM_QUICK_RISE",
46 "WAVEFORM_SLOW_RISE",
47 "WAVEFORM_QUICK_FALL",
48 "WAVEFORM_LIGHT_TICK",
49 "WAVEFORM_LOW_TICK",
50 "WAVEFORM_RESERVED_MFG_1",
51 "WAVEFORM_RESERVED_MFG_2",
52 "WAVEFORM_RESERVED_MFG_3",
53 "WAVEFORM_COMPOSE",
54 "WAVEFORM_PWLE",
55 "INVALID"};
56 static const char *kLatencyLookup[] = {"kWaveformEffectLatency", "kPrebakedEffectLatency",
57 "kCompositionEffectLatency", "kPwleEffectLatency",
58 "INVALID"};
59 static const char *kErrorLookup[] = {"kInitError",
60 "kHwApiError",
61 "kHwCalError",
62 "kComposeFailError",
63 "kAlsaFailError",
64 "kAsyncFailError",
65 "kBadTimeoutError",
66 "kBadAmplitudeError",
67 "kBadEffectError",
68 "kBadEffectStrengthError",
69 "kBadPrimitiveError",
70 "kBadCompositeError",
71 "kPwleConstructionFailError",
72 "kUnsupportedOpError",
73 "INVALID"};
74
waveformToString(uint16_t index)75 const char *waveformToString(uint16_t index) {
76 return kWaveformLookup[(index < ARRAY_SIZE(kWaveformLookup)) ? index
77 : ARRAY_SIZE(kWaveformLookup) - 1];
78 }
79
latencyToString(uint16_t index)80 const char *latencyToString(uint16_t index) {
81 return kLatencyLookup[(index < ARRAY_SIZE(kLatencyLookup)) ? index
82 : ARRAY_SIZE(kLatencyLookup) - 1];
83 }
84
errorToString(uint16_t index)85 const char *errorToString(uint16_t index) {
86 return kErrorLookup[(index < ARRAY_SIZE(kErrorLookup)) ? index : ARRAY_SIZE(kErrorLookup) - 1];
87 }
88
89 #define STATS_TRACE(...) \
90 ATRACE_NAME(__func__); \
91 ALOGD(__VA_ARGS__)
92 #else
93 #define STATS_TRACE(...) ATRACE_NAME(__func__)
94 #define waveformToString(x)
95 #define latencyToString(x)
96 #define errorToString(x)
97 #endif
98
99 namespace aidl {
100 namespace android {
101 namespace hardware {
102 namespace vibrator {
103
104 enum EffectLatency : uint16_t {
105 kWaveformEffectLatency = 0,
106 kPrebakedEffectLatency,
107 kCompositionEffectLatency,
108 kPwleEffectLatency,
109
110 kEffectLatencyCount
111 };
112
113 enum VibratorError : uint16_t {
114 kInitError = 0,
115 kHwApiError,
116 kHwCalError,
117 kComposeFailError,
118 kAlsaFailError,
119 kAsyncFailError,
120 kBadTimeoutError,
121 kBadAmplitudeError,
122 kBadEffectError,
123 kBadEffectStrengthError,
124 kBadPrimitiveError,
125 kBadCompositeError,
126 kPwleConstructionFailError,
127 kUnsupportedOpError,
128
129 kVibratorErrorCount
130 };
131
132 class StatsApi : public Vibrator::StatsApi, private StatsBase {
133 public:
StatsApi()134 StatsApi()
135 : StatsBase(std::string(std::getenv("STATS_INSTANCE"))),
136 mCurrentLatencyIndex(kEffectLatencyCount) {
137 mWaveformCounts = std::vector<int32_t>(WAVEFORM_MAX_INDEX, 0);
138 mDurationCounts = std::vector<int32_t>(DURATION_BUCKET_COUNT, 0);
139 mMinLatencies = std::vector<int32_t>(kEffectLatencyCount, 0);
140 mMaxLatencies = std::vector<int32_t>(kEffectLatencyCount, 0);
141 mLatencyTotals = std::vector<int32_t>(kEffectLatencyCount, 0);
142 mLatencyCounts = std::vector<int32_t>(kEffectLatencyCount, 0);
143 mErrorCounts = std::vector<int32_t>(kVibratorErrorCount, 0);
144 }
145
logPrimitive(uint16_t effectIndex)146 bool logPrimitive(uint16_t effectIndex) override {
147 STATS_TRACE("logPrimitive(effectIndex: %s)", waveformToString(effectIndex));
148
149 if (effectIndex >= WAVEFORM_MAX_PHYSICAL_INDEX ||
150 effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX ||
151 effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX) {
152 ALOGE("Invalid waveform index for logging primitive: %d", effectIndex);
153 return false;
154 }
155
156 {
157 std::scoped_lock<std::mutex> lock(mDataAccess);
158 mWaveformCounts[effectIndex]++;
159 }
160
161 return true;
162 }
163
logWaveform(uint16_t effectIndex,int32_t duration)164 bool logWaveform(uint16_t effectIndex, int32_t duration) override {
165 STATS_TRACE("logWaveform(effectIndex: %s, duration: %d)", waveformToString(effectIndex),
166 duration);
167
168 if (effectIndex != WAVEFORM_LONG_VIBRATION_EFFECT_INDEX &&
169 effectIndex != WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX) {
170 ALOGE("Invalid waveform index for logging waveform: %d", effectIndex);
171 return false;
172 }
173
174 if (duration > MAX_TIME_MS || duration < 0) {
175 ALOGE("Invalid waveform duration for logging waveform: %d", duration);
176 return false;
177 }
178
179 {
180 std::scoped_lock<std::mutex> lock(mDataAccess);
181 mWaveformCounts[effectIndex]++;
182 if (duration < DURATION_BUCKET_WIDTH * DURATION_50MS_BUCKET_COUNT) {
183 mDurationCounts[duration / DURATION_BUCKET_WIDTH]++;
184 } else {
185 mDurationCounts[DURATION_50MS_BUCKET_COUNT]++;
186 }
187 }
188
189 return true;
190 }
191
logError(uint16_t errorIndex)192 bool logError(uint16_t errorIndex) override {
193 STATS_TRACE("logError(errorIndex: %s)", errorToString(errorIndex));
194
195 if (errorIndex >= kVibratorErrorCount) {
196 ALOGE("Invalid index for logging error: %d", errorIndex);
197 return false;
198 }
199
200 {
201 std::scoped_lock<std::mutex> lock(mDataAccess);
202 mErrorCounts[errorIndex]++;
203 }
204
205 return true;
206 }
207
logLatencyStart(uint16_t latencyIndex)208 bool logLatencyStart(uint16_t latencyIndex) override {
209 STATS_TRACE("logLatencyStart(latencyIndex: %s)", latencyToString(latencyIndex));
210
211 if (latencyIndex >= kEffectLatencyCount) {
212 ALOGE("Invalid index for measuring latency: %d", latencyIndex);
213 return false;
214 }
215
216 mCurrentLatencyStart = std::chrono::steady_clock::now();
217 mCurrentLatencyIndex = latencyIndex;
218
219 return true;
220 }
221
logLatencyEnd()222 bool logLatencyEnd() override {
223 STATS_TRACE("logLatencyEnd()");
224
225 if (mCurrentLatencyIndex >= kEffectLatencyCount) {
226 return false;
227 }
228
229 int32_t latency = (std::chrono::duration_cast<std::chrono::milliseconds>(
230 std::chrono::steady_clock::now() - mCurrentLatencyStart))
231 .count();
232
233 {
234 std::scoped_lock<std::mutex> lock(mDataAccess);
235 if (latency < mMinLatencies[mCurrentLatencyIndex] ||
236 mMinLatencies[mCurrentLatencyIndex] == 0) {
237 mMinLatencies[mCurrentLatencyIndex] = latency;
238 }
239 if (latency > mMaxLatencies[mCurrentLatencyIndex]) {
240 mMaxLatencies[mCurrentLatencyIndex] = latency;
241 }
242 mLatencyTotals[mCurrentLatencyIndex] += latency;
243 mLatencyCounts[mCurrentLatencyIndex]++;
244 }
245
246 mCurrentLatencyIndex = kEffectLatencyCount;
247 return true;
248 }
249
debug(int fd)250 void debug(int fd) override { StatsBase::debug(fd); }
251
252 private:
253 uint16_t mCurrentLatencyIndex;
254 std::chrono::time_point<std::chrono::steady_clock> mCurrentLatencyStart;
255 };
256
257 } // namespace vibrator
258 } // namespace hardware
259 } // namespace android
260 } // namespace aidl
261