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