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