1 /*
2 * Copyright (c) 2023 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 "default_vibrator_decoder.h"
17
18 #include <algorithm>
19 #include <cinttypes>
20
21 #include "sensors_errors.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "DefaultVibratorDecoder"
25
26 namespace OHOS {
27 namespace Sensors {
28 namespace {
29 constexpr int32_t STARTTMIE_MIN = 0;
30 constexpr int32_t STARTTMIE_MAX = 1800000;
31 constexpr int32_t CONTINUOUS_VIBRATION_DURATION_MIN = 0;
32 constexpr int32_t CONTINUOUS_VIBRATION_DURATION_MAX = 5000;
33 constexpr int32_t TRANSIENT_VIBRATION_DURATION = 48;
34 constexpr int32_t INTENSITY_MIN = 0;
35 constexpr int32_t INTENSITY_MAX = 100;
36 constexpr int32_t FREQUENCY_MIN = 0;
37 constexpr int32_t FREQUENCY_MAX = 100;
38 constexpr int32_t EVENT_NUM_MAX = 128;
39 constexpr double SUPPORT_JSON_VERSION = 1.0;
40 constexpr int32_t SUPPORT_CHANNEL_NUMBER = 3;
41 constexpr uint32_t PATTERN_CAPACITY = 16;
42 constexpr uint32_t CURVE_POINT_MIN = 4;
43 constexpr uint32_t CURVE_POINT_MAX = 16;
44 constexpr int32_t CURVE_INTENSITY_MIN = 0;
45 constexpr int32_t CURVE_INTENSITY_MAX = 100;
46 constexpr int32_t CURVE_INTENSITY_SCALE = 100;
47 constexpr int32_t CURVE_FREQUENCY_MIN = -100;
48 constexpr int32_t CURVE_FREQUENCY_MAX = 100;
49 constexpr int32_t MAX_JSON_FILE_SIZE = 64 * 1024;
50 } // namespace
51
DecodeEffect(const RawFileDescriptor & rawFd,const JsonParser & parser,VibratePackage & patternPackage)52 int32_t DefaultVibratorDecoder::DecodeEffect(const RawFileDescriptor &rawFd, const JsonParser &parser,
53 VibratePackage &patternPackage) __attribute__((no_sanitize("cfi")))
54 {
55 if ((rawFd.fd < 0) || (rawFd.offset < 0) || (rawFd.length <= 0) || (rawFd.length > MAX_JSON_FILE_SIZE)) {
56 MISC_HILOGE("Invalid file descriptor, fd:%{public}d, offset:%{public}" PRId64 ", length:%{public}" PRId64,
57 rawFd.fd, rawFd.offset, rawFd.length);
58 return PARAMETER_ERROR;
59 }
60 int32_t ret = CheckMetadata(parser);
61 if (ret != SUCCESS) {
62 MISC_HILOGE("Check metadata fail");
63 return ret;
64 }
65 VibratePattern originPattern;
66 ret = ParseChannel(parser, originPattern, patternPackage);
67 if (ret != SUCCESS) {
68 MISC_HILOGE("Parse channel fail");
69 return ret;
70 }
71 MISC_HILOGD("packageDuration:%{public}d", patternPackage.packageDuration);
72 PatternSplit(originPattern, patternPackage);
73 return SUCCESS;
74 }
75
CheckMetadata(const JsonParser & parser)76 int32_t DefaultVibratorDecoder::CheckMetadata(const JsonParser &parser)
77 {
78 cJSON *metadataItem = parser.GetObjectItem("MetaData");
79 CHKPR(metadataItem, ERROR);
80 cJSON *versionItem = parser.GetObjectItem(metadataItem, "Version");
81 CHKPR(versionItem, ERROR);
82 version_ = parser.GetDoubleValue(versionItem);
83 if (version_ != SUPPORT_JSON_VERSION) {
84 MISC_HILOGE("Json file version is not supported, version:%{public}f", version_);
85 return ERROR;
86 }
87 cJSON *channelNumberItem = parser.GetObjectItem(metadataItem, "ChannelNumber");
88 CHKPR(channelNumberItem, ERROR);
89 channelNumber_ = parser.GetIntValue(channelNumberItem);
90 if ((channelNumber_ <= 0)|| (channelNumber_ >= SUPPORT_CHANNEL_NUMBER)) {
91 MISC_HILOGE("Json file channelNumber is not supported, channelNumber:%{public}d", channelNumber_);
92 return ERROR;
93 }
94 return SUCCESS;
95 }
96
ParseChannel(const JsonParser & parser,VibratePattern & originPattern,VibratePackage & patternPackage)97 int32_t DefaultVibratorDecoder::ParseChannel(const JsonParser &parser, VibratePattern &originPattern,
98 VibratePackage &patternPackage)
99 {
100 cJSON *channelsItem = parser.GetObjectItem("Channels");
101 CHKPR(channelsItem, ERROR);
102 if (!parser.IsArray(channelsItem)) {
103 MISC_HILOGE("The value of channels is not array");
104 return ERROR;
105 }
106 int32_t size = parser.GetArraySize(channelsItem);
107 if (size != channelNumber_) {
108 MISC_HILOGE("The size of channels conflicts with channelNumber, size:%{public}d", size);
109 return ERROR;
110 }
111 int32_t parseDuration = 0;
112 for (int32_t i = 0; i < size; i++) {
113 cJSON *channelItem = parser.GetArrayItem(channelsItem, i);
114 CHKPR(channelItem, ERROR);
115 cJSON *channelParametersItem = parser.GetObjectItem(channelItem, "Parameters");
116 CHKPR(channelParametersItem, ERROR);
117 int32_t ret = ParseChannelParameters(parser, channelParametersItem);
118 CHKCR((ret == SUCCESS), ERROR, "parse channel parameters fail");
119 cJSON *patternItem = parser.GetObjectItem(channelItem, "Pattern");
120 CHKPR(patternItem, ERROR);
121 ret = ParsePattern(parser, patternItem, originPattern);
122 parseDuration += originPattern.patternDuration;
123 CHKCR((ret == SUCCESS), ERROR, "parse pattern fail");
124 }
125 patternPackage.packageDuration = parseDuration;
126 std::sort(originPattern.events.begin(), originPattern.events.end());
127 return SUCCESS;
128 }
129
ParseChannelParameters(const JsonParser & parser,cJSON * channelParametersItem)130 int32_t DefaultVibratorDecoder::ParseChannelParameters(const JsonParser &parser, cJSON *channelParametersItem)
131 {
132 cJSON *indexItem = parser.GetObjectItem(channelParametersItem, "Index");
133 CHKPR(indexItem, ERROR);
134 int32_t indexVal = parser.GetIntValue(indexItem);
135 CHKCR((indexVal >= 0) && (indexVal < SUPPORT_CHANNEL_NUMBER), ERROR, "invalid channel index");
136 return SUCCESS;
137 }
138
ParsePattern(const JsonParser & parser,cJSON * patternItem,VibratePattern & originPattern)139 int32_t DefaultVibratorDecoder::ParsePattern(const JsonParser &parser, cJSON *patternItem,
140 VibratePattern &originPattern)
141 {
142 if (!parser.IsArray(patternItem)) {
143 MISC_HILOGE("The value of pattern is not array");
144 return ERROR;
145 }
146 int32_t size = parser.GetArraySize(patternItem);
147 if (size > EVENT_NUM_MAX) {
148 MISC_HILOGE("The size of pattern is out of bounds, size:%{public}d", size);
149 return ERROR;
150 }
151 int32_t vibratorDuration = 0;
152 for (int32_t i = 0; i < size; i++) {
153 cJSON *item = parser.GetArrayItem(patternItem, i);
154 CHKPR(item, ERROR);
155 cJSON *eventItem = parser.GetObjectItem(item, "Event");
156 CHKPR(eventItem, ERROR);
157 VibrateEvent event;
158 int32_t ret = ParseEvent(parser, eventItem, event);
159 CHKCR((ret == SUCCESS), ERROR, "parse event fail");
160 vibratorDuration += event.duration;
161 originPattern.events.emplace_back(event);
162 }
163 originPattern.patternDuration = vibratorDuration;
164 return SUCCESS;
165 }
166
ParseEvent(const JsonParser & parser,cJSON * eventItem,VibrateEvent & event)167 int32_t DefaultVibratorDecoder::ParseEvent(const JsonParser &parser, cJSON *eventItem, VibrateEvent &event)
168 {
169 cJSON *typeItem = parser.GetObjectItem(eventItem, "Type");
170 CHKPR(typeItem, ERROR);
171 std::string curType = parser.GetStringValue(typeItem);
172 if (curType == "continuous") {
173 event.tag = EVENT_TAG_CONTINUOUS;
174 cJSON *durationItem = parser.GetObjectItem(eventItem, "Duration");
175 CHKPR(durationItem, ERROR);
176 event.duration = parser.GetIntValue(durationItem);
177 } else if (curType == "transient") {
178 event.tag = EVENT_TAG_TRANSIENT;
179 event.duration = TRANSIENT_VIBRATION_DURATION;
180 } else {
181 MISC_HILOGE("Unknown event type, curType:%{public}s", curType.c_str());
182 return ERROR;
183 }
184 cJSON *startTimeItem = parser.GetObjectItem(eventItem, "StartTime");
185 CHKPR(startTimeItem, ERROR);
186 event.time = parser.GetIntValue(startTimeItem);
187 cJSON *eventParametersItem = parser.GetObjectItem(eventItem, "Parameters");
188 CHKPR(eventParametersItem, ERROR);
189 cJSON *intensityItem = parser.GetObjectItem(eventParametersItem, "Intensity");
190 CHKPR(intensityItem, ERROR);
191 event.intensity = parser.GetIntValue(intensityItem);
192 cJSON *frequencyItem = parser.GetObjectItem(eventParametersItem, "Frequency");
193 CHKPR(frequencyItem, ERROR);
194 event.frequency = parser.GetIntValue(frequencyItem);
195 if (!CheckEventParameters(event)) {
196 MISC_HILOGE("Parameter check of vibration event failed, startTime:%{public}d", event.time);
197 return ERROR;
198 }
199 if ((curType == "continuous") && parser.HasObjectItem(eventParametersItem, "Curve")) {
200 cJSON *curveItem = parser.GetObjectItem(eventParametersItem, "Curve");
201 CHKPR(curveItem, ERROR);
202 int32_t ret = ParseCurve(parser, curveItem, event);
203 if (ret != SUCCESS) {
204 MISC_HILOGE("Parse curve fail, startTime:%{public}d", event.time);
205 return ERROR;
206 }
207 }
208 return SUCCESS;
209 }
210
CheckEventParameters(const VibrateEvent & event)211 bool DefaultVibratorDecoder::CheckEventParameters(const VibrateEvent &event)
212 {
213 if (event.time < STARTTMIE_MIN || event.time > STARTTMIE_MAX) {
214 MISC_HILOGE("The event startTime is out of range, startTime:%{public}d", event.time);
215 return false;
216 }
217 if (event.duration < CONTINUOUS_VIBRATION_DURATION_MIN ||
218 event.duration > CONTINUOUS_VIBRATION_DURATION_MAX) {
219 MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration);
220 return false;
221 }
222 if (event.intensity < INTENSITY_MIN || event.intensity > INTENSITY_MAX) {
223 MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity);
224 return false;
225 }
226 if (event.frequency < FREQUENCY_MIN || event.frequency > FREQUENCY_MAX) {
227 MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
228 return false;
229 }
230 return true;
231 }
232
ParseCurve(const JsonParser & parser,cJSON * curveItem,VibrateEvent & event)233 int32_t DefaultVibratorDecoder::ParseCurve(const JsonParser &parser, cJSON *curveItem, VibrateEvent &event)
234 {
235 if (!parser.IsArray(curveItem)) {
236 MISC_HILOGE("The value of curve is not array");
237 return ERROR;
238 }
239 size_t size = static_cast<size_t>(parser.GetArraySize(curveItem));
240 if ((size < CURVE_POINT_MIN) || (size > CURVE_POINT_MAX)) {
241 MISC_HILOGE("The size of curve point is out of bounds, size:%{public}zu", size);
242 return ERROR;
243 }
244 for (size_t i = 0; i < size; i++) {
245 VibrateCurvePoint point;
246 cJSON *item = parser.GetArrayItem(curveItem, i);
247 CHKPR(item, ERROR);
248 cJSON *timeItem = parser.GetObjectItem(item, "Time");
249 CHKPR(timeItem, ERROR);
250 point.time = parser.GetIntValue(timeItem);
251 if ((point.time < 0) || (point.time > event.duration)) {
252 MISC_HILOGE("The time of curve point is out of bounds, time:%{public}d", point.time);
253 return ERROR;
254 }
255 cJSON *intensityItem = parser.GetObjectItem(item, "Intensity");
256 CHKPR(intensityItem, ERROR);
257 point.intensity = (parser.GetDoubleValue(intensityItem)) * CURVE_INTENSITY_SCALE;
258 if ((point.intensity < CURVE_INTENSITY_MIN) || (point.intensity > CURVE_INTENSITY_MAX)) {
259 MISC_HILOGE("The intensity of curve point is out of bounds, intensity:%{public}d", point.intensity);
260 return ERROR;
261 }
262 cJSON *frequencyItem = parser.GetObjectItem(item, "Frequency");
263 CHKPR(frequencyItem, ERROR);
264 point.frequency = parser.GetIntValue(frequencyItem);
265 if ((point.frequency < CURVE_FREQUENCY_MIN) || (point.frequency > CURVE_FREQUENCY_MAX)) {
266 MISC_HILOGE("The frequency of curve point is out of bounds, frequency:%{public}d", point.frequency);
267 return ERROR;
268 }
269 event.points.emplace_back(point);
270 }
271 std::sort(event.points.begin(), event.points.end());
272 return SUCCESS;
273 }
274
PatternSplit(VibratePattern & originPattern,VibratePackage & patternPackage)275 void DefaultVibratorDecoder::PatternSplit(VibratePattern &originPattern,
276 VibratePackage &patternPackage) __attribute__((no_sanitize("cfi")))
277 {
278 if (originPattern.events.empty()) {
279 MISC_HILOGI("The origin pattern is empty");
280 return;
281 }
282 VibratePattern slicePattern;
283 slicePattern.startTime = originPattern.events[0].time;
284 size_t size = originPattern.events.size();
285 for (size_t i = 0; i < size; ++i) {
286 originPattern.events[i].time -= slicePattern.startTime;
287 slicePattern.events.emplace_back(originPattern.events[i]);
288 if ((slicePattern.events.size() >= PATTERN_CAPACITY) || (i == (size - 1))) {
289 patternPackage.patterns.emplace_back(slicePattern);
290 slicePattern.events.clear();
291 slicePattern.startTime = ((i < size - 1) ? originPattern.events[i + 1].time : 0);
292 }
293 }
294 }
295 } // namespace Sensors
296 } // namespace OHOS