• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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