1 /*
2 * Copyright (c) 2023 Shanghai Ruisheng Kaitai Acoustic Science 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 "he_vibrator_decoder.h"
17
18 #include "sensors_errors.h"
19
20 #undef LOG_TAG
21 #define LOG_TAG "HEVibratorDecoder"
22
23 namespace OHOS {
24 namespace Sensors {
25 namespace {
26 constexpr int32_t EVENT_NUM_MAX = 16;
27 constexpr int32_t SUPPORTED_HE_VERSION_1 = 1;
28 constexpr int32_t SUPPORTED_HE_VERSION_2 = 2;
29 constexpr int32_t INDEX_MIN = 0;
30 constexpr int32_t INDEX_MAX = 2;
31 constexpr int32_t TRANSIENT_VIBRATION_DURATION = 48;
32 constexpr int32_t INTENSITY_MIN = 0;
33 constexpr int32_t INTENSITY_MAX = 100;
34 constexpr int32_t CONTINUOUS_FREQUENCY_MIN = 0;
35 constexpr int32_t CONTINUOUS_FREQUENCY_MAX = 100;
36 constexpr int32_t TRANSIENT_FREQUENCY_MIN = -50;
37 constexpr int32_t TRANSIENT_FREQUENCY_MAX = 150;
38 constexpr int32_t CURVE_POINT_NUM_MIN = 4;
39 constexpr int32_t CURVE_POINT_NUM_MAX = 16;
40 constexpr int32_t CURVE_INTENSITY_MIN = 0;
41 constexpr int32_t CURVE_INTENSITY_MAX = 100;
42 constexpr int32_t CURVE_INTENSITY_SCALE = 100;
43 constexpr int32_t CURVE_FREQUENCY_MIN = -100;
44 constexpr int32_t CURVE_FREQUENCY_MAX = 100;
45 constexpr int32_t CONTINUOUS_DURATION_MAX = 5000;
46 } // namespace
47
DecodeEffect(const RawFileDescriptor & rawFd,VibratePackage & pkg)48 int32_t HEVibratorDecoder::DecodeEffect(const RawFileDescriptor &rawFd, VibratePackage &pkg)
49 {
50 JsonParser parser(rawFd);
51 int32_t version = ParseVersion(parser);
52 pkg.patterns.clear();
53 switch (version) {
54 case SUPPORTED_HE_VERSION_1: {
55 cJSON *patternJSON = parser.GetObjectItem("Pattern");
56 CHKPR(patternJSON, ERROR);
57 VibratePattern pattern;
58 pattern.startTime = 0;
59 int32_t ret = ParsePattern(parser, patternJSON, pattern);
60 CHKCR((ret == SUCCESS), ERROR, "parse pattern fail!");
61 pkg.patterns.emplace_back(pattern);
62 break;
63 }
64 case SUPPORTED_HE_VERSION_2: {
65 cJSON *patternListJSON = parser.GetObjectItem("PatternList");
66 CHKPR(patternListJSON, ERROR);
67 int32_t ret = ParsePatternList(parser, patternListJSON, pkg);
68 CHKCR((ret == SUCCESS), ERROR, "parse pattern list fail!");
69 break;
70 }
71 default: {
72 MISC_HILOGE("unsupported version %{public}d", version);
73 return ERROR;
74 }
75 }
76 return SUCCESS;
77 }
78
ParseVersion(const JsonParser & parser)79 int32_t HEVibratorDecoder::ParseVersion(const JsonParser &parser)
80 {
81 cJSON *metadataJSON = parser.GetObjectItem("Metadata");
82 CHKPR(metadataJSON, ERROR);
83 cJSON *versionJSON = parser.GetObjectItem(metadataJSON, "Version");
84 CHKPR(versionJSON, ERROR);
85 return cJSON_IsNumber(versionJSON) ? versionJSON->valueint : -1;
86 }
87
ParsePatternList(const JsonParser & parser,cJSON * patternListJSON,VibratePackage & pkg)88 int32_t HEVibratorDecoder::ParsePatternList(const JsonParser &parser, cJSON *patternListJSON, VibratePackage &pkg)
89 {
90 if (!parser.IsArray(patternListJSON)) {
91 MISC_HILOGE("The value of pattern list is not array!");
92 return ERROR;
93 }
94 int32_t size = parser.GetArraySize(patternListJSON);
95 if (size <= 0) {
96 MISC_HILOGE("The size of pattern list %{public}d is invalid!", size);
97 return ERROR;
98 }
99 int32_t previousPattternTime = -1;
100 for (int32_t i = 0; i < size; i++) {
101 cJSON *patternListItemJSON = parser.GetArrayItem(patternListJSON, i);
102 CHKPR(patternListItemJSON, ERROR);
103 cJSON *timeJSON = parser.GetObjectItem(patternListItemJSON, "AbsoluteTime");
104 CHKPR(timeJSON, ERROR);
105 int32_t time = cJSON_IsNumber(timeJSON) ? timeJSON->valueint : -1;
106 if (time <= previousPattternTime) {
107 MISC_HILOGE("The value of absolute time %{public}d is invalid!", time);
108 return ERROR;
109 }
110 previousPattternTime = time;
111 cJSON *patternJSON = parser.GetObjectItem(patternListItemJSON, "Pattern");
112 CHKPR(patternJSON, ERROR);
113 VibratePattern pattern;
114 pattern.startTime = time;
115 int32_t ret = ParsePattern(parser, patternJSON, pattern);
116 CHKCR((ret == SUCCESS), ERROR, "parse pattern fail!");
117 pkg.patterns.emplace_back(pattern);
118 }
119 return SUCCESS;
120 }
121
ParsePattern(const JsonParser & parser,cJSON * patternJSON,VibratePattern & pattern)122 int32_t HEVibratorDecoder::ParsePattern(const JsonParser &parser, cJSON *patternJSON, VibratePattern &pattern)
123 {
124 if (!parser.IsArray(patternJSON)) {
125 MISC_HILOGE("The value of pattern is not array");
126 return ERROR;
127 }
128 int32_t size = parser.GetArraySize(patternJSON);
129 if (size <= 0 || size > EVENT_NUM_MAX) {
130 MISC_HILOGE("The size of pattern is out of bounds, size:%{public}d", size);
131 return ERROR;
132 }
133 int32_t previousEventTime = 0;
134 for (int32_t i = 0; i < size; i++) {
135 cJSON *patternItemJSON = parser.GetArrayItem(patternJSON, i);
136 CHKPR(patternItemJSON, ERROR);
137 cJSON *eventJSON = parser.GetObjectItem(patternItemJSON, "Event");
138 CHKPR(eventJSON, ERROR);
139 VibrateEvent event;
140 int32_t ret = ParseEvent(parser, eventJSON, event);
141 CHKCR((ret == SUCCESS), ERROR, "parse event fail!");
142 if (event.time < previousEventTime) {
143 MISC_HILOGE("The value of absolute time %{public}d is invalid!", event.time);
144 return ERROR;
145 }
146 previousEventTime = event.time;
147 pattern.events.emplace_back(event);
148 }
149 return SUCCESS;
150 }
151
ParseEvent(const JsonParser & parser,cJSON * eventJSON,VibrateEvent & event)152 int32_t HEVibratorDecoder::ParseEvent(const JsonParser &parser, cJSON *eventJSON, VibrateEvent &event)
153 {
154 cJSON *typeJSON = parser.GetObjectItem(eventJSON, "Type");
155 CHKPR(typeJSON, ERROR);
156 std::string type = cJSON_IsString(typeJSON) ? typeJSON->valuestring : "";
157 if (type == "transient") {
158 event.tag = EVENT_TAG_TRANSIENT;
159 event.duration = TRANSIENT_VIBRATION_DURATION;
160 } else if (type == "continuous") {
161 event.tag = EVENT_TAG_CONTINUOUS;
162 cJSON *durationJSON = parser.GetObjectItem(eventJSON, "Duration");
163 CHKPR(durationJSON, ERROR);
164 event.duration = cJSON_IsNumber(durationJSON) ? durationJSON->valueint : -1;
165 } else {
166 MISC_HILOGE("Unknown event type %{public}s", type.c_str());
167 return ERROR;
168 }
169 cJSON *indexJSON = parser.GetObjectItem(eventJSON, "Index");
170 if (indexJSON != NULL) {
171 event.index = cJSON_IsNumber(indexJSON) ? indexJSON->valueint : -1;
172 } else {
173 event.index = 0;
174 }
175 cJSON *timeJSON = parser.GetObjectItem(eventJSON, "RelativeTime");
176 CHKPR(timeJSON, ERROR);
177 event.time = cJSON_IsNumber(timeJSON) ? timeJSON->valueint : -1;
178 cJSON *paramJSON = parser.GetObjectItem(eventJSON, "Parameters");
179 CHKPR(paramJSON, ERROR);
180 cJSON *intensityJSON = parser.GetObjectItem(paramJSON, "Intensity");
181 CHKPR(intensityJSON, ERROR);
182 event.intensity = cJSON_IsNumber(intensityJSON) ? intensityJSON->valueint : -1;
183 cJSON *frequencyJSON = parser.GetObjectItem(paramJSON, "Frequency");
184 CHKPR(frequencyJSON, ERROR);
185 event.frequency = cJSON_IsNumber(frequencyJSON) ? frequencyJSON->valueint : -1;
186 if (event.tag == EVENT_TAG_CONTINUOUS) {
187 cJSON *curveJSON = parser.GetObjectItem(paramJSON, "Curve");
188 CHKPR(curveJSON, ERROR);
189 int32_t ret = ParseCurve(parser, curveJSON, event);
190 if (ret != SUCCESS) {
191 MISC_HILOGE("Parse curve fail, startTime:%{public}d", event.time);
192 return ERROR;
193 }
194 }
195 if (!CheckEventParameters(event)) {
196 MISC_HILOGE("Parameter check of vibration event failed, startTime:%{public}d", event.time);
197 return ERROR;
198 }
199 return SUCCESS;
200 }
201
ParseCurve(const JsonParser & parser,cJSON * curveJSON,VibrateEvent & event)202 int32_t HEVibratorDecoder::ParseCurve(const JsonParser &parser, cJSON *curveJSON, VibrateEvent &event)
203 {
204 if (!parser.IsArray(curveJSON)) {
205 MISC_HILOGE("The value of curve is not array");
206 return ERROR;
207 }
208 int32_t size = parser.GetArraySize(curveJSON);
209 if ((size < CURVE_POINT_NUM_MIN) || (size > CURVE_POINT_NUM_MAX)) {
210 MISC_HILOGE("The size of curve point is out of bounds, size:%{public}d", size);
211 return ERROR;
212 }
213 int32_t previousCurveTime = -1;
214 for (int32_t i = 0; i < size; i++) {
215 VibrateCurvePoint point;
216 cJSON *itemJSON = parser.GetArrayItem(curveJSON, i);
217 CHKPR(itemJSON, ERROR);
218 cJSON *timeJSON = parser.GetObjectItem(itemJSON, "Time");
219 CHKPR(timeJSON, ERROR);
220 point.time = cJSON_IsNumber(timeJSON) ? timeJSON->valueint : -1;
221 if (point.time <= previousCurveTime || point.time > event.duration) {
222 MISC_HILOGE("The time of curve point is invalid, time:%{public}d", point.time);
223 return ERROR;
224 }
225 previousCurveTime = point.time;
226 cJSON *intensityJSON = parser.GetObjectItem(itemJSON, "Intensity");
227 CHKPR(intensityJSON, ERROR);
228 point.intensity = cJSON_IsNumber(intensityJSON) ? (intensityJSON->valuedouble) * CURVE_INTENSITY_SCALE : -1;
229 if (point.intensity < CURVE_INTENSITY_MIN || point.intensity > CURVE_INTENSITY_MAX) {
230 MISC_HILOGE("The intensity of curve point is invalid, intensity:%{public}d", point.intensity);
231 return ERROR;
232 }
233 cJSON *frequencyJSON = parser.GetObjectItem(itemJSON, "Frequency");
234 CHKPR(frequencyJSON, ERROR);
235 point.frequency = cJSON_IsNumber(frequencyJSON) ? frequencyJSON->valueint : -1;
236 if (point.frequency < CURVE_FREQUENCY_MIN || point.frequency > CURVE_FREQUENCY_MAX) {
237 MISC_HILOGE("The freq of curve point is invalid, freq:%{public}d", point.frequency);
238 return ERROR;
239 }
240 event.points.emplace_back(point);
241 }
242 return SUCCESS;
243 }
244
CheckEventParameters(const VibrateEvent & event)245 bool HEVibratorDecoder::CheckEventParameters(const VibrateEvent &event)
246 {
247 if (!CheckCommonParameters(event)) {
248 return false;
249 }
250 if (event.tag == EVENT_TAG_TRANSIENT) {
251 return CheckTransientParameters(event);
252 } else if (event.tag == EVENT_TAG_CONTINUOUS) {
253 return CheckContinuousParameters(event);
254 } else {
255 MISC_HILOGE("The event tag is unknown, tag:%{public}d", event.tag);
256 return false;
257 }
258 return true;
259 }
260
CheckCommonParameters(const VibrateEvent & event)261 bool HEVibratorDecoder::CheckCommonParameters(const VibrateEvent &event)
262 {
263 if (event.time < 0) {
264 MISC_HILOGE("The event startTime is out of range, startTime:%{public}d", event.time);
265 return false;
266 }
267 if (event.index < INDEX_MIN || event.index > INDEX_MAX) {
268 MISC_HILOGE("The event index is out of range, index:%{public}d", event.index);
269 return false;
270 }
271 if (event.intensity < INTENSITY_MIN || event.intensity > INTENSITY_MAX) {
272 MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity);
273 return false;
274 }
275 return true;
276 }
277
CheckTransientParameters(const VibrateEvent & event)278 bool HEVibratorDecoder::CheckTransientParameters(const VibrateEvent &event)
279 {
280 if (event.frequency < TRANSIENT_FREQUENCY_MIN || event.frequency > TRANSIENT_FREQUENCY_MAX) {
281 MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
282 return false;
283 }
284 return true;
285 }
286
CheckContinuousParameters(const VibrateEvent & event)287 bool HEVibratorDecoder::CheckContinuousParameters(const VibrateEvent &event)
288 {
289 if (event.frequency < CONTINUOUS_FREQUENCY_MIN || event.frequency > CONTINUOUS_FREQUENCY_MAX) {
290 MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
291 return false;
292 }
293 if (event.duration <= 0 || event.duration > CONTINUOUS_DURATION_MAX) {
294 MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration);
295 return false;
296 }
297 int32_t pointNum = event.points.size();
298 if (pointNum < CURVE_POINT_NUM_MIN || pointNum > CURVE_POINT_NUM_MAX) {
299 MISC_HILOGE("The points size is out of range, size:%{public}d", pointNum);
300 return false;
301 }
302 if (event.points[0].time != 0 || event.points[0].intensity != 0) {
303 MISC_HILOGE("The fist curve point is invalivd, time %{public}d, insentsity %{public}d", event.points[0].time,
304 event.points[0].intensity);
305 return false;
306 }
307 if (event.points[pointNum - 1].time != event.duration || event.points[pointNum - 1].intensity != 0) {
308 MISC_HILOGE("The last curve point is invalivd, time %{public}d, insentsity %{public}d",
309 event.points[pointNum - 1].time, event.points[pointNum - 1].intensity);
310 return false;
311 }
312 return true;
313 }
314 } // namespace Sensors
315 } // namespace OHOS