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