1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "vibrator_thread.h"
17
18 #include <sys/prctl.h>
19
20 #include "custom_vibration_matcher.h"
21 #include "sensors_errors.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "VibratorThread"
25
26 namespace OHOS {
27 namespace Sensors {
28 namespace {
29 const std::string VIBRATE_CONTROL_THREAD_NAME = "OS_VibControl";
30 constexpr int32_t DELAY_TIME1 = 5; /** ms */
31 constexpr int32_t DELAY_TIME2 = 10; /** ms */
32 constexpr size_t RETRY_NUMBER = 6;
33 constexpr int32_t MAX_VIBRATE_COUNT = 1000;
34 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
35 constexpr size_t COMPOSITE_EFFECT_PART = 128;
36 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
37 } // namespace
38
Run()39 bool VibratorThread::Run()
40 {
41 CALL_LOG_ENTER;
42 prctl(PR_SET_NAME, VIBRATE_CONTROL_THREAD_NAME.c_str());
43 VibrateInfo info = GetCurrentVibrateInfo();
44 VibratorIdentifierIPC identifier = GetCurrentVibrateParams();
45 std::vector<HdfWaveInformation> waveInfos = GetCurrentWaveInfo();
46 MISC_HILOGD("info.mode:%{public}s, deviceId:%{public}d, vibratorId:%{public}d",
47 info.mode.c_str(), identifier.deviceId, identifier.vibratorId);
48 if (info.mode == VIBRATE_TIME) {
49 int32_t ret = PlayOnce(info, identifier);
50 if (ret != SUCCESS) {
51 MISC_HILOGE("Play once vibration fail, package:%{public}s", info.packageName.c_str());
52 return false;
53 }
54 } else if (info.mode == VIBRATE_PRESET) {
55 int32_t ret = PlayEffect(info, identifier);
56 if (ret != SUCCESS) {
57 MISC_HILOGE("Play effect vibration fail, package:%{public}s", info.packageName.c_str());
58 return false;
59 }
60 } else if (info.mode == VIBRATE_CUSTOM_HD) {
61 int32_t ret = PlayCustomByHdHptic(info, identifier);
62 if (ret != SUCCESS) {
63 MISC_HILOGE("Play custom vibration by hd haptic fail, package:%{public}s", info.packageName.c_str());
64 return false;
65 }
66 } else if (info.mode == VIBRATE_CUSTOM_COMPOSITE_EFFECT || info.mode == VIBRATE_CUSTOM_COMPOSITE_TIME) {
67 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
68 int32_t ret = PlayCustomByCompositeEffect(info, identifier, waveInfos);
69 if (ret != SUCCESS) {
70 MISC_HILOGE("Play custom vibration by composite effect fail, package:%{public}s", info.packageName.c_str());
71 return false;
72 }
73 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
74 }
75 return false;
76 }
77
PlayOnce(const VibrateInfo & info,const VibratorIdentifierIPC & identifier)78 int32_t VibratorThread::PlayOnce(const VibrateInfo &info, const VibratorIdentifierIPC& identifier)
79 {
80 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
81 int32_t ret = VibratorDevice.StartOnce(identifier, static_cast<uint32_t>(info.duration));
82 if (ret != SUCCESS) {
83 MISC_HILOGE("StartOnce fail, duration:%{public}d", info.duration);
84 return ERROR;
85 }
86 cv_.wait_for(vibrateLck, std::chrono::milliseconds(info.duration), [this] { return exitFlag_.load(); });
87 if (exitFlag_) {
88 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
89 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_ONCE);
90 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
91 MISC_HILOGD("Stop duration:%{public}d, package:%{public}s", info.duration, info.packageName.c_str());
92 return SUCCESS;
93 }
94 return SUCCESS;
95 }
96
HandleMultipleVibrations(const VibratorIdentifierIPC & identifier)97 void VibratorThread::HandleMultipleVibrations(const VibratorIdentifierIPC& identifier)
98 {
99 if (VibratorDevice.IsVibratorRunning(identifier)) {
100 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_PRESET);
101 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_HDHAPTIC);
102 for (size_t i = 0; i < RETRY_NUMBER; i++) {
103 if (!VibratorDevice.IsVibratorRunning(identifier)) {
104 MISC_HILOGI("No running vibration");
105 return;
106 }
107 std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TIME1));
108 }
109 MISC_HILOGW("Unstopped vibration");
110 }
111 }
112
PlayEffect(const VibrateInfo & info,const VibratorIdentifierIPC & identifier)113 int32_t VibratorThread::PlayEffect(const VibrateInfo &info, const VibratorIdentifierIPC& identifier)
114 {
115 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
116 if (info.count < 0 || info.count > MAX_VIBRATE_COUNT) {
117 MISC_HILOGE("Vibratorinfo's count is invalid, count:%{public}d", info.count);
118 return ERROR;
119 }
120 for (int32_t i = 0; i < info.count; ++i) {
121 std::string effect = info.effect;
122 int32_t duration = info.duration;
123 if (i >= 1) { /**Multiple vibration treatment*/
124 HandleMultipleVibrations(identifier);
125 duration += DELAY_TIME2;
126 }
127 int32_t ret = VibratorDevice.StartByIntensity(identifier, effect, info.intensity);
128 if (ret != SUCCESS) {
129 MISC_HILOGE("Vibrate effect %{public}s failed, ", effect.c_str());
130 return ERROR;
131 }
132 cv_.wait_for(vibrateLck, std::chrono::milliseconds(duration), [this] { return exitFlag_.load(); });
133 if (exitFlag_) {
134 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
135 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_PRESET);
136 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
137 MISC_HILOGD("Stop effect:%{public}s, package:%{public}s", effect.c_str(), info.packageName.c_str());
138 return SUCCESS;
139 }
140 }
141 return SUCCESS;
142 }
143
PlayCustomByHdHptic(const VibrateInfo & info,const VibratorIdentifierIPC & identifier)144 int32_t VibratorThread::PlayCustomByHdHptic(const VibrateInfo &info, const VibratorIdentifierIPC& identifier)
145 {
146 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
147 const std::vector<VibratePattern> &patterns = info.package.patterns;
148 size_t patternSize = patterns.size();
149 for (size_t i = 0; i < patternSize; ++i) {
150 int32_t delayTime;
151 if (i == 0) {
152 delayTime = patterns[i].startTime;
153 } else {
154 delayTime = patterns[i].startTime - patterns[i - 1].startTime;
155 }
156 cv_.wait_for(vibrateLck, std::chrono::milliseconds(delayTime), [this] { return exitFlag_.load(); });
157 if (exitFlag_) {
158 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
159 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_HDHAPTIC);
160 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
161 MISC_HILOGD("Stop hd haptic, package:%{public}s", info.packageName.c_str());
162 return SUCCESS;
163 }
164 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
165 HandleMultipleVibrations(identifier);
166 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
167 int32_t ret = VibratorDevice.PlayPattern(identifier, patterns[i]);
168 if (ret != SUCCESS) {
169 MISC_HILOGE("Vibrate hd haptic failed");
170 return ERROR;
171 }
172 }
173 return SUCCESS;
174 }
175
copyInfoWithIndexEvents(const VibrateInfo & originalInfo,const VibratorIdentifierIPC & identifier)176 VibrateInfo VibratorThread::copyInfoWithIndexEvents(const VibrateInfo& originalInfo,
177 const VibratorIdentifierIPC& identifier)
178 {
179 VibrateInfo newInfo = originalInfo;
180 VibratePackage newPackage;
181 int32_t parseDuration = 0;
182
183 for (const auto& pattern : originalInfo.package.patterns) {
184 VibratePattern newPattern;
185 newPattern.startTime = pattern.startTime;
186 newPattern.patternDuration = pattern.patternDuration;
187
188 for (const auto& event : pattern.events) {
189 if (event.index == 0 || event.index == identifier.position) {
190 newPattern.events.push_back(event);
191 parseDuration = event.duration;
192 }
193 }
194
195 if (!newPattern.events.empty()) {
196 newPackage.patterns.push_back(newPattern);
197 }
198 }
199
200 newInfo.package = newPackage;
201 newInfo.package.packageDuration = parseDuration;
202 return newInfo;
203 }
204
205 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
PlayCustomByCompositeEffect(const VibrateInfo & info,const VibratorIdentifierIPC & identifier,const std::vector<HdfWaveInformation> & waveInfo)206 int32_t VibratorThread::PlayCustomByCompositeEffect(const VibrateInfo &info, const VibratorIdentifierIPC& identifier,
207 const std::vector<HdfWaveInformation> &waveInfo)
208 {
209 CustomVibrationMatcher matcher(identifier, waveInfo);
210 HdfCompositeEffect hdfCompositeEffect;
211 VibrateInfo newInfo = copyInfoWithIndexEvents(info, identifier);
212 if (newInfo.mode == VIBRATE_CUSTOM_COMPOSITE_EFFECT) {
213 hdfCompositeEffect.type = HDF_EFFECT_TYPE_PRIMITIVE;
214 int32_t ret = matcher.TransformEffect(newInfo.package, hdfCompositeEffect.compositeEffects);
215 if (ret != SUCCESS) {
216 MISC_HILOGE("Transform pattern to predefined wave fail");
217 return ERROR;
218 }
219 } else if (newInfo.mode == VIBRATE_CUSTOM_COMPOSITE_TIME) {
220 hdfCompositeEffect.type = HDF_EFFECT_TYPE_TIME;
221 int32_t ret = matcher.TransformTime(info.package, hdfCompositeEffect.compositeEffects);
222 if (ret != SUCCESS) {
223 MISC_HILOGE("Transform pattern to time series fail");
224 return ERROR;
225 }
226 }
227 return PlayCompositeEffect(newInfo, hdfCompositeEffect, identifier);
228 }
229
PlayCompositeEffect(const VibrateInfo & info,const HdfCompositeEffect & hdfCompositeEffect,const VibratorIdentifierIPC & identifier)230 int32_t VibratorThread::PlayCompositeEffect(const VibrateInfo &info, const HdfCompositeEffect &hdfCompositeEffect,
231 const VibratorIdentifierIPC& identifier)
232 {
233 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
234 HdfCompositeEffect effectsPart;
235 effectsPart.type = hdfCompositeEffect.type;
236 size_t effectSize = hdfCompositeEffect.compositeEffects.size();
237 int32_t delayTime = 0;
238 for (size_t i = 0; i < effectSize; ++i) {
239 effectsPart.compositeEffects.push_back(hdfCompositeEffect.compositeEffects[i]);
240 if (effectsPart.type == HDF_EFFECT_TYPE_TIME) {
241 delayTime += hdfCompositeEffect.compositeEffects[i].timeEffect.delay;
242 } else if (effectsPart.type == HDF_EFFECT_TYPE_PRIMITIVE) {
243 delayTime += hdfCompositeEffect.compositeEffects[i].primitiveEffect.delay;
244 } else {
245 MISC_HILOGE("Effect type is valid");
246 return ERROR;
247 }
248 if ((effectsPart.compositeEffects.size() >= COMPOSITE_EFFECT_PART) || (i == (effectSize - 1))) {
249 int32_t ret = VibratorDevice.EnableCompositeEffect(identifier, effectsPart);
250 if (ret != SUCCESS) {
251 MISC_HILOGE("EnableCompositeEffect failed");
252 return ERROR;
253 }
254 cv_.wait_for(vibrateLck, std::chrono::milliseconds(delayTime), [this] { return exitFlag_.load(); });
255 delayTime = 0;
256 effectsPart.compositeEffects.clear();
257 }
258 if (exitFlag_) {
259 VibratorDevice.Stop(identifier, HDF_VIBRATOR_MODE_PRESET);
260 MISC_HILOGD("Stop composite effect part, package:%{public}s", info.packageName.c_str());
261 return SUCCESS;
262 }
263 }
264 return SUCCESS;
265 }
266 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
267
UpdateVibratorEffect(const VibrateInfo & info,const VibratorIdentifierIPC & identifier,std::vector<HdfWaveInformation> & waveInfos)268 void VibratorThread::UpdateVibratorEffect(const VibrateInfo &info, const VibratorIdentifierIPC& identifier,
269 std::vector<HdfWaveInformation> &waveInfos)
270 {
271 std::unique_lock<std::mutex> lck(currentVibrationMutex_);
272 currentVibration_ = info;
273 currentVibrateParams_ = identifier;
274 waveInfos_ = waveInfos;
275 }
276
GetCurrentVibrateInfo()277 VibrateInfo VibratorThread::GetCurrentVibrateInfo()
278 {
279 std::unique_lock<std::mutex> lck(currentVibrationMutex_);
280 return currentVibration_;
281 }
282
GetCurrentVibrateParams()283 VibratorIdentifierIPC VibratorThread::GetCurrentVibrateParams()
284 {
285 std::unique_lock<std::mutex> lck(currentVibrateParamsMutex_);
286 return currentVibrateParams_;
287 }
288
GetCurrentWaveInfo()289 std::vector<HdfWaveInformation> VibratorThread::GetCurrentWaveInfo()
290 {
291 std::unique_lock<std::mutex> lck(currentVibrateParamsMutex_);
292 return waveInfos_;
293 }
294
SetExitStatus(bool status)295 void VibratorThread::SetExitStatus(bool status)
296 {
297 exitFlag_.store(status);
298 }
299
WakeUp()300 void VibratorThread::WakeUp()
301 {
302 MISC_HILOGD("Notify the vibratorThread");
303 cv_.notify_one();
304 }
305
ResetVibrateInfo()306 void VibratorThread::ResetVibrateInfo()
307 {
308 std::unique_lock<std::mutex> lck(currentVibrationMutex_);
309 currentVibration_.mode = "";
310 currentVibration_.packageName = "";
311 currentVibration_.pid = -1;
312 currentVibration_.uid = -1;
313 currentVibration_.usage = 0;
314 currentVibration_.systemUsage = false;
315 currentVibration_.duration = 0;
316 currentVibration_.effect = "";
317 currentVibration_.count = 0;
318 currentVibration_.intensity = 0;
319 }
320 } // namespace Sensors
321 } // namespace OHOS
322