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