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 = 4;
33 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
34 constexpr size_t COMPOSITE_EFFECT_PART = 128;
35 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
36 } // namespace
37
Run()38 bool VibratorThread::Run()
39 {
40 CALL_LOG_ENTER;
41 prctl(PR_SET_NAME, VIBRATE_CONTROL_THREAD_NAME.c_str());
42 VibrateInfo info = GetCurrentVibrateInfo();
43 if (info.mode == VIBRATE_TIME) {
44 int32_t ret = PlayOnce(info);
45 if (ret != SUCCESS) {
46 MISC_HILOGE("Play once vibration fail, package:%{public}s", info.packageName.c_str());
47 return false;
48 }
49 } else if (info.mode == VIBRATE_PRESET) {
50 int32_t ret = PlayEffect(info);
51 if (ret != SUCCESS) {
52 MISC_HILOGE("Play effect vibration fail, package:%{public}s", info.packageName.c_str());
53 return false;
54 }
55 } else if (info.mode == VIBRATE_CUSTOM_HD) {
56 int32_t ret = PlayCustomByHdHptic(info);
57 if (ret != SUCCESS) {
58 MISC_HILOGE("Play custom vibration by hd haptic fail, package:%{public}s", info.packageName.c_str());
59 return false;
60 }
61 } else if (info.mode == VIBRATE_CUSTOM_COMPOSITE_EFFECT || info.mode == VIBRATE_CUSTOM_COMPOSITE_TIME) {
62 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
63 int32_t ret = PlayCustomByCompositeEffect(info);
64 if (ret != SUCCESS) {
65 MISC_HILOGE("Play custom vibration by composite effect fail, package:%{public}s", info.packageName.c_str());
66 return false;
67 }
68 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
69 }
70 return false;
71 }
72
PlayOnce(const VibrateInfo & info)73 int32_t VibratorThread::PlayOnce(const VibrateInfo &info)
74 {
75 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
76 int32_t ret = VibratorDevice.StartOnce(static_cast<uint32_t>(info.duration));
77 if (ret != SUCCESS) {
78 MISC_HILOGE("StartOnce fail, duration:%{public}d", info.duration);
79 return ERROR;
80 }
81 cv_.wait_for(vibrateLck, std::chrono::milliseconds(info.duration), [this] { return exitFlag_.load(); });
82 if (exitFlag_) {
83 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
84 VibratorDevice.Stop(HDF_VIBRATOR_MODE_ONCE);
85 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
86 MISC_HILOGD("Stop duration:%{public}d, package:%{public}s", info.duration, info.packageName.c_str());
87 return SUCCESS;
88 }
89 return SUCCESS;
90 }
91
HandleMultipleVibrations()92 void VibratorThread::HandleMultipleVibrations()
93 {
94 if (VibratorDevice.IsVibratorRunning()) {
95 VibratorDevice.Stop(HDF_VIBRATOR_MODE_PRESET);
96 for (size_t i = 0; i < RETRY_NUMBER; i++) {
97 if (!VibratorDevice.IsVibratorRunning()) {
98 MISC_HILOGI("No running vibration");
99 return;
100 }
101 std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TIME1));
102 }
103 MISC_HILOGW("Unstopped vibration");
104 }
105 }
106
PlayEffect(const VibrateInfo & info)107 int32_t VibratorThread::PlayEffect(const VibrateInfo &info)
108 {
109 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
110 for (int32_t i = 0; i < info.count; ++i) {
111 std::string effect = info.effect;
112 int32_t duration = info.duration;
113 if (i >= 1) { /**Multiple vibration treatment*/
114 HandleMultipleVibrations();
115 duration += DELAY_TIME2;
116 }
117 int32_t ret = VibratorDevice.StartByIntensity(effect, info.intensity);
118 if (ret != SUCCESS) {
119 MISC_HILOGE("Vibrate effect %{public}s failed, ", effect.c_str());
120 return ERROR;
121 }
122 cv_.wait_for(vibrateLck, std::chrono::milliseconds(duration), [this] { return exitFlag_.load(); });
123 if (exitFlag_) {
124 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
125 VibratorDevice.Stop(HDF_VIBRATOR_MODE_PRESET);
126 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
127 MISC_HILOGD("Stop effect:%{public}s, package:%{public}s", effect.c_str(), info.packageName.c_str());
128 return SUCCESS;
129 }
130 }
131 return SUCCESS;
132 }
133
PlayCustomByHdHptic(const VibrateInfo & info)134 int32_t VibratorThread::PlayCustomByHdHptic(const VibrateInfo &info)
135 {
136 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
137 const std::vector<VibratePattern> &patterns = info.package.patterns;
138 size_t patternSize = patterns.size();
139 for (size_t i = 0; i < patternSize; ++i) {
140 int32_t delayTime;
141 if (i == 0) {
142 delayTime = patterns[i].startTime;
143 } else {
144 delayTime = patterns[i].startTime - patterns[i - 1].startTime;
145 }
146 cv_.wait_for(vibrateLck, std::chrono::milliseconds(delayTime), [this] { return exitFlag_.load(); });
147 if (exitFlag_) {
148 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
149 VibratorDevice.Stop(HDF_VIBRATOR_MODE_HDHAPTIC);
150 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
151 MISC_HILOGD("Stop hd haptic, package:%{public}s", info.packageName.c_str());
152 return SUCCESS;
153 }
154 int32_t ret = VibratorDevice.PlayPattern(patterns[i]);
155 if (ret != SUCCESS) {
156 MISC_HILOGE("Vibrate hd haptic failed");
157 return ERROR;
158 }
159 }
160 return SUCCESS;
161 }
162
163 #ifdef HDF_DRIVERS_INTERFACE_VIBRATOR
PlayCustomByCompositeEffect(const VibrateInfo & info)164 int32_t VibratorThread::PlayCustomByCompositeEffect(const VibrateInfo &info)
165 {
166 auto &matcher = CustomVibrationMatcher::GetInstance();
167 HdfCompositeEffect hdfCompositeEffect;
168 if (info.mode == VIBRATE_CUSTOM_COMPOSITE_EFFECT) {
169 hdfCompositeEffect.type = HDF_EFFECT_TYPE_PRIMITIVE;
170 int32_t ret = matcher.TransformEffect(info.package, hdfCompositeEffect.compositeEffects);
171 if (ret != SUCCESS) {
172 MISC_HILOGE("Transform pattern to predefined wave fail");
173 return ERROR;
174 }
175 } else if (info.mode == VIBRATE_CUSTOM_COMPOSITE_TIME) {
176 hdfCompositeEffect.type = HDF_EFFECT_TYPE_TIME;
177 int32_t ret = matcher.TransformTime(info.package, hdfCompositeEffect.compositeEffects);
178 if (ret != SUCCESS) {
179 MISC_HILOGE("Transform pattern to time series fail");
180 return ERROR;
181 }
182 }
183 return PlayCompositeEffect(info, hdfCompositeEffect);
184 }
185
PlayCompositeEffect(const VibrateInfo & info,const HdfCompositeEffect & hdfCompositeEffect)186 int32_t VibratorThread::PlayCompositeEffect(const VibrateInfo &info, const HdfCompositeEffect &hdfCompositeEffect)
187 {
188 std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
189 HdfCompositeEffect effectsPart;
190 effectsPart.type = hdfCompositeEffect.type;
191 size_t effectSize = hdfCompositeEffect.compositeEffects.size();
192 int32_t delayTime = 0;
193 for (size_t i = 0; i < effectSize; ++i) {
194 effectsPart.compositeEffects.push_back(hdfCompositeEffect.compositeEffects[i]);
195 if (effectsPart.type == HDF_EFFECT_TYPE_TIME) {
196 delayTime += hdfCompositeEffect.compositeEffects[i].timeEffect.delay;
197 } else if (effectsPart.type == HDF_EFFECT_TYPE_PRIMITIVE) {
198 delayTime += hdfCompositeEffect.compositeEffects[i].primitiveEffect.delay;
199 } else {
200 MISC_HILOGE("Effect type is valid");
201 return ERROR;
202 }
203 if ((effectsPart.compositeEffects.size() >= COMPOSITE_EFFECT_PART) || (i == (effectSize - 1))) {
204 int32_t ret = VibratorDevice.EnableCompositeEffect(effectsPart);
205 if (ret != SUCCESS) {
206 MISC_HILOGE("EnableCompositeEffect failed");
207 return ERROR;
208 }
209 cv_.wait_for(vibrateLck, std::chrono::milliseconds(delayTime), [this] { return exitFlag_.load(); });
210 delayTime = 0;
211 effectsPart.compositeEffects.clear();
212 }
213 if (exitFlag_) {
214 VibratorDevice.Stop(HDF_VIBRATOR_MODE_PRESET);
215 MISC_HILOGD("Stop composite effect part, package:%{public}s", info.packageName.c_str());
216 return SUCCESS;
217 }
218 }
219 return SUCCESS;
220 }
221 #endif // HDF_DRIVERS_INTERFACE_VIBRATOR
222
UpdateVibratorEffect(const VibrateInfo & info)223 void VibratorThread::UpdateVibratorEffect(const VibrateInfo &info)
224 {
225 std::unique_lock<std::mutex> lck(currentVibrationMutex_);
226 currentVibration_ = info;
227 }
228
GetCurrentVibrateInfo()229 VibrateInfo VibratorThread::GetCurrentVibrateInfo()
230 {
231 std::unique_lock<std::mutex> lck(currentVibrationMutex_);
232 return currentVibration_;
233 }
234
SetExitStatus(bool status)235 void VibratorThread::SetExitStatus(bool status)
236 {
237 exitFlag_.store(status);
238 }
239
WakeUp()240 void VibratorThread::WakeUp()
241 {
242 MISC_HILOGD("Notify the vibratorThread");
243 cv_.notify_one();
244 }
245 } // namespace Sensors
246 } // namespace OHOS
247