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