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