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