• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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