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