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,const JsonParser & parser,VibratePackage & pkg)48 int32_t HEVibratorDecoder::DecodeEffect(const RawFileDescriptor &rawFd, const JsonParser &parser,
49 VibratePackage &pkg)
50 {
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 if (parser.HasObjectItem(eventJSON, "Index")) {
170 cJSON *indexJSON = parser.GetObjectItem(eventJSON, "Index");
171 CHKPR(indexJSON, ERROR);
172 event.index = cJSON_IsNumber(indexJSON) ? indexJSON->valueint : -1;
173 } else {
174 event.index = 0;
175 }
176 cJSON *timeJSON = parser.GetObjectItem(eventJSON, "RelativeTime");
177 CHKPR(timeJSON, ERROR);
178 event.time = cJSON_IsNumber(timeJSON) ? timeJSON->valueint : -1;
179 cJSON *paramJSON = parser.GetObjectItem(eventJSON, "Parameters");
180 CHKPR(paramJSON, ERROR);
181 cJSON *intensityJSON = parser.GetObjectItem(paramJSON, "Intensity");
182 CHKPR(intensityJSON, ERROR);
183 event.intensity = cJSON_IsNumber(intensityJSON) ? intensityJSON->valueint : -1;
184 cJSON *frequencyJSON = parser.GetObjectItem(paramJSON, "Frequency");
185 CHKPR(frequencyJSON, ERROR);
186 event.frequency = cJSON_IsNumber(frequencyJSON) ? frequencyJSON->valueint : -1;
187 if (event.tag == EVENT_TAG_CONTINUOUS) {
188 cJSON *curveJSON = parser.GetObjectItem(paramJSON, "Curve");
189 CHKPR(curveJSON, ERROR);
190 int32_t ret = ParseCurve(parser, curveJSON, event);
191 if (ret != SUCCESS) {
192 MISC_HILOGE("Parse curve fail, startTime:%{public}d", event.time);
193 return ERROR;
194 }
195 }
196 if (!CheckEventParameters(event)) {
197 MISC_HILOGE("Parameter check of vibration event failed, startTime:%{public}d", event.time);
198 return ERROR;
199 }
200 return SUCCESS;
201 }
202
ParseCurve(const JsonParser & parser,cJSON * curveJSON,VibrateEvent & event)203 int32_t HEVibratorDecoder::ParseCurve(const JsonParser &parser, cJSON *curveJSON, VibrateEvent &event)
204 {
205 if (!parser.IsArray(curveJSON)) {
206 MISC_HILOGE("The value of curve is not array");
207 return ERROR;
208 }
209 int32_t size = parser.GetArraySize(curveJSON);
210 if ((size < CURVE_POINT_NUM_MIN) || (size > CURVE_POINT_NUM_MAX)) {
211 MISC_HILOGE("The size of curve point is out of bounds, size:%{public}d", size);
212 return ERROR;
213 }
214 int32_t previousCurveTime = -1;
215 for (int32_t i = 0; i < size; i++) {
216 VibrateCurvePoint point;
217 cJSON *itemJSON = parser.GetArrayItem(curveJSON, i);
218 CHKPR(itemJSON, ERROR);
219 cJSON *timeJSON = parser.GetObjectItem(itemJSON, "Time");
220 CHKPR(timeJSON, ERROR);
221 point.time = cJSON_IsNumber(timeJSON) ? timeJSON->valueint : -1;
222 if (point.time <= previousCurveTime || point.time > event.duration) {
223 MISC_HILOGE("The time of curve point is invalid, time:%{public}d", point.time);
224 return ERROR;
225 }
226 previousCurveTime = point.time;
227 cJSON *intensityJSON = parser.GetObjectItem(itemJSON, "Intensity");
228 CHKPR(intensityJSON, ERROR);
229 point.intensity = cJSON_IsNumber(intensityJSON) ? (intensityJSON->valuedouble) * CURVE_INTENSITY_SCALE : -1;
230 if (point.intensity < CURVE_INTENSITY_MIN || point.intensity > CURVE_INTENSITY_MAX) {
231 MISC_HILOGE("The intensity of curve point is invalid, intensity:%{public}d", point.intensity);
232 return ERROR;
233 }
234 cJSON *frequencyJSON = parser.GetObjectItem(itemJSON, "Frequency");
235 CHKPR(frequencyJSON, ERROR);
236 point.frequency = cJSON_IsNumber(frequencyJSON) ? frequencyJSON->valueint : -1;
237 if (point.frequency < CURVE_FREQUENCY_MIN || point.frequency > CURVE_FREQUENCY_MAX) {
238 MISC_HILOGE("The freq of curve point is invalid, freq:%{public}d", point.frequency);
239 return ERROR;
240 }
241 event.points.emplace_back(point);
242 }
243 return SUCCESS;
244 }
245
CheckEventParameters(const VibrateEvent & event)246 bool HEVibratorDecoder::CheckEventParameters(const VibrateEvent &event)
247 {
248 if (!CheckCommonParameters(event)) {
249 return false;
250 }
251 if (event.tag == EVENT_TAG_TRANSIENT) {
252 return CheckTransientParameters(event);
253 } else if (event.tag == EVENT_TAG_CONTINUOUS) {
254 return CheckContinuousParameters(event);
255 } else {
256 MISC_HILOGE("The event tag is unknown, tag:%{public}d", event.tag);
257 return false;
258 }
259 return true;
260 }
261
CheckCommonParameters(const VibrateEvent & event)262 bool HEVibratorDecoder::CheckCommonParameters(const VibrateEvent &event)
263 {
264 if (event.time < 0) {
265 MISC_HILOGE("The event startTime is out of range, startTime:%{public}d", event.time);
266 return false;
267 }
268 if (event.index < INDEX_MIN || event.index > INDEX_MAX) {
269 MISC_HILOGE("The event index is out of range, index:%{public}d", event.index);
270 return false;
271 }
272 if (event.intensity < INTENSITY_MIN || event.intensity > INTENSITY_MAX) {
273 MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity);
274 return false;
275 }
276 return true;
277 }
278
CheckTransientParameters(const VibrateEvent & event)279 bool HEVibratorDecoder::CheckTransientParameters(const VibrateEvent &event)
280 {
281 if (event.frequency < TRANSIENT_FREQUENCY_MIN || event.frequency > TRANSIENT_FREQUENCY_MAX) {
282 MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
283 return false;
284 }
285 return true;
286 }
287
CheckContinuousParameters(const VibrateEvent & event)288 bool HEVibratorDecoder::CheckContinuousParameters(const VibrateEvent &event)
289 {
290 if (event.frequency < CONTINUOUS_FREQUENCY_MIN || event.frequency > CONTINUOUS_FREQUENCY_MAX) {
291 MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
292 return false;
293 }
294 if (event.duration <= 0 || event.duration > CONTINUOUS_DURATION_MAX) {
295 MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration);
296 return false;
297 }
298 int32_t pointNum = static_cast<int32_t>(event.points.size());
299 if (pointNum < CURVE_POINT_NUM_MIN || pointNum > CURVE_POINT_NUM_MAX) {
300 MISC_HILOGE("The points size is out of range, size:%{public}d", pointNum);
301 return false;
302 }
303 if (event.points[0].time != 0 || event.points[0].intensity != 0) {
304 MISC_HILOGE("The fist curve point is invalivd, time %{public}d, insentsity %{public}d", event.points[0].time,
305 event.points[0].intensity);
306 return false;
307 }
308 if (event.points[pointNum - 1].time != event.duration || event.points[pointNum - 1].intensity != 0) {
309 MISC_HILOGE("The last curve point is invalivd, time %{public}d, insentsity %{public}d",
310 event.points[pointNum - 1].time, event.points[pointNum - 1].intensity);
311 return false;
312 }
313 return true;
314 }
315 } // namespace Sensors
316 } // namespace OHOS