• 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 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.StartByIntensity(effect, info.intensity);
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             VibratorDevice.Stop(HDF_VIBRATOR_MODE_HDHAPTIC);
118             MISC_HILOGD("Stop hd haptic, package:%{public}s", info.packageName.c_str());
119             return SUCCESS;
120         }
121         int32_t ret = VibratorDevice.PlayPattern(patterns[i]);
122         if (ret != SUCCESS) {
123             MISC_HILOGE("Vibrate hd haptic failed");
124             return ERROR;
125         }
126     }
127     return SUCCESS;
128 }
129 
PlayCustomByCompositeEffect(const VibrateInfo & info)130 int32_t VibratorThread::PlayCustomByCompositeEffect(const VibrateInfo &info)
131 {
132     auto &matcher = CustomVibrationMatcher::GetInstance();
133     HdfCompositeEffect hdfCompositeEffect;
134     if (info.mode == VIBRATE_CUSTOM_COMPOSITE_EFFECT) {
135         hdfCompositeEffect.type = HDF_EFFECT_TYPE_PRIMITIVE;
136         int32_t ret = matcher.TransformEffect(info.package, hdfCompositeEffect.compositeEffects);
137         if (ret != SUCCESS) {
138             MISC_HILOGE("Transform pattern to predefined wave fail");
139             return ERROR;
140         }
141     } else if (info.mode == VIBRATE_CUSTOM_COMPOSITE_TIME) {
142         hdfCompositeEffect.type = HDF_EFFECT_TYPE_TIME;
143         int32_t ret = matcher.TransformTime(info.package, hdfCompositeEffect.compositeEffects);
144         if (ret != SUCCESS) {
145             MISC_HILOGE("Transform pattern to time series fail");
146             return ERROR;
147         }
148     }
149     return PlayCompositeEffect(info, hdfCompositeEffect);
150 }
151 
PlayCompositeEffect(const VibrateInfo & info,const HdfCompositeEffect & hdfCompositeEffect)152 int32_t VibratorThread::PlayCompositeEffect(const VibrateInfo &info, const HdfCompositeEffect &hdfCompositeEffect)
153 {
154     std::unique_lock<std::mutex> vibrateLck(vibrateMutex_);
155     HdfCompositeEffect effectsPart;
156     effectsPart.type = hdfCompositeEffect.type;
157     size_t effectSize = hdfCompositeEffect.compositeEffects.size();
158     int32_t delayTime = 0;
159     for (size_t i = 0; i < effectSize; ++i) {
160         effectsPart.compositeEffects.push_back(hdfCompositeEffect.compositeEffects[i]);
161         if (effectsPart.type == HDF_EFFECT_TYPE_TIME) {
162             delayTime += hdfCompositeEffect.compositeEffects[i].timeEffect.delay;
163         } else if (effectsPart.type == HDF_EFFECT_TYPE_PRIMITIVE) {
164             delayTime += hdfCompositeEffect.compositeEffects[i].primitiveEffect.delay;
165         } else {
166             MISC_HILOGE("Effect type is valid");
167             return ERROR;
168         }
169         if ((effectsPart.compositeEffects.size() >= COMPOSITE_EFFECT_PART) || (i == (effectSize - 1))) {
170             int32_t ret = VibratorDevice.EnableCompositeEffect(effectsPart);
171             if (ret != SUCCESS) {
172                 MISC_HILOGE("EnableCompositeEffect failed");
173                 return ERROR;
174             }
175             cv_.wait_for(vibrateLck, std::chrono::milliseconds(delayTime), [this] { return exitFlag_.load(); });
176             delayTime = 0;
177             effectsPart.compositeEffects.clear();
178         }
179         if (exitFlag_) {
180             VibratorDevice.Stop(HDF_VIBRATOR_MODE_PRESET);
181             MISC_HILOGD("Stop composite effect part, package:%{public}s", info.packageName.c_str());
182             return SUCCESS;
183         }
184     }
185     return SUCCESS;
186 }
187 
UpdateVibratorEffect(const VibrateInfo & info)188 void VibratorThread::UpdateVibratorEffect(const VibrateInfo &info)
189 {
190     std::unique_lock<std::mutex> lck(currentVibrationMutex_);
191     currentVibration_ = info;
192 }
193 
GetCurrentVibrateInfo()194 VibrateInfo VibratorThread::GetCurrentVibrateInfo()
195 {
196     std::unique_lock<std::mutex> lck(currentVibrationMutex_);
197     return currentVibration_;
198 }
199 
SetExitStatus(bool status)200 void VibratorThread::SetExitStatus(bool status)
201 {
202     exitFlag_.store(status);
203 }
204 
WakeUp()205 void VibratorThread::WakeUp()
206 {
207     MISC_HILOGD("Notify the vibratorThread");
208     cv_.notify_one();
209 }
210 }  // namespace Sensors
211 }  // namespace OHOS
212