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