• 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 "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