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