• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cinttypes>
19 
20 #include "sensors_errors.h"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "DefaultVibratorDecoder"
24 
25 namespace OHOS {
26 namespace Sensors {
27 namespace {
28 constexpr int32_t STARTTMIE_MIN = 0;
29 constexpr int32_t STARTTMIE_MAX = 1800000;
30 constexpr int32_t CONTINUOUS_VIBRATION_DURATION_MIN = 0;
31 constexpr int32_t CONTINUOUS_VIBRATION_DURATION_MAX = 5000;
32 constexpr int32_t TRANSIENT_VIBRATION_DURATION = 48;
33 constexpr int32_t INTENSITY_MIN = 0;
34 constexpr int32_t INTENSITY_MAX = 100;
35 constexpr int32_t FREQUENCY_MIN = 0;
36 constexpr int32_t FREQUENCY_MAX = 100;
37 constexpr int32_t EVENT_NUM_MAX = 128;
38 constexpr double SUPPORT_JSON_VERSION = 1.0;
39 constexpr int32_t SUPPORT_CHANNEL_NUMBER = 3;
40 constexpr uint32_t PATTERN_CAPACITY = 16;
41 constexpr uint32_t CURVE_POINT_MIN = 4;
42 constexpr uint32_t CURVE_POINT_MAX = 16;
43 constexpr int32_t CURVE_INTENSITY_MIN = 0;
44 constexpr int32_t CURVE_INTENSITY_MAX = 100;
45 constexpr int32_t CURVE_INTENSITY_SCALE = 100;
46 constexpr int32_t CURVE_FREQUENCY_MIN = -100;
47 constexpr int32_t CURVE_FREQUENCY_MAX = 100;
48 constexpr int32_t MAX_JSON_FILE_SIZE = 64 * 1024;
49 } // namespace
50 
DecodeEffect(const RawFileDescriptor & rawFd,const JsonParser & parser,VibratePackage & patternPackage)51 int32_t DefaultVibratorDecoder::DecodeEffect(const RawFileDescriptor &rawFd, const JsonParser &parser,
52     VibratePackage &patternPackage) __attribute__((no_sanitize("cfi")))
53 {
54     if ((rawFd.fd < 0) || (rawFd.offset < 0) || (rawFd.length <= 0) || (rawFd.length > MAX_JSON_FILE_SIZE)) {
55         MISC_HILOGE("Invalid file descriptor, fd:%{public}d, offset:%{public}" PRId64 ", length:%{public}" PRId64,
56             rawFd.fd, rawFd.offset, rawFd.length);
57         return PARAMETER_ERROR;
58     }
59     int32_t ret = CheckMetadata(parser);
60     if (ret != SUCCESS) {
61         MISC_HILOGE("Check metadata fail");
62         return ret;
63     }
64     VibratePattern originPattern;
65     ret = ParseChannel(parser, originPattern, patternPackage);
66     if (ret != SUCCESS) {
67         MISC_HILOGE("Parse channel fail");
68         return ret;
69     }
70     MISC_HILOGD("packageDuration:%{public}d", patternPackage.packageDuration);
71     PatternSplit(originPattern, patternPackage);
72     return SUCCESS;
73 }
74 
CheckMetadata(const JsonParser & parser)75 int32_t DefaultVibratorDecoder::CheckMetadata(const JsonParser &parser)
76 {
77     cJSON *metadataItem = parser.GetObjectItem("MetaData");
78     CHKPR(metadataItem, ERROR);
79     cJSON *versionItem = parser.GetObjectItem(metadataItem, "Version");
80     CHKPR(versionItem, ERROR);
81     version_ = parser.GetDoubleValue(versionItem);
82     if (version_ != SUPPORT_JSON_VERSION) {
83         MISC_HILOGE("Json file version is not supported, version:%{public}f", version_);
84         return ERROR;
85     }
86     cJSON *channelNumberItem = parser.GetObjectItem(metadataItem, "ChannelNumber");
87     CHKPR(channelNumberItem, ERROR);
88     channelNumber_ = parser.GetIntValue(channelNumberItem);
89     if ((channelNumber_ <= 0)|| (channelNumber_ >= SUPPORT_CHANNEL_NUMBER)) {
90         MISC_HILOGE("Json file channelNumber is not supported, channelNumber:%{public}d", channelNumber_);
91         return ERROR;
92     }
93     return SUCCESS;
94 }
95 
ParseChannel(const JsonParser & parser,VibratePattern & originPattern,VibratePackage & patternPackage)96 int32_t DefaultVibratorDecoder::ParseChannel(const JsonParser &parser, VibratePattern &originPattern,
97     VibratePackage &patternPackage) __attribute__((no_sanitize("cfi")))
98 {
99     cJSON *channelsItem = parser.GetObjectItem("Channels");
100     CHKPR(channelsItem, ERROR);
101     if (!parser.IsArray(channelsItem)) {
102         MISC_HILOGE("The value of channels is not array");
103         return ERROR;
104     }
105     int32_t size = parser.GetArraySize(channelsItem);
106     if (size != channelNumber_) {
107         MISC_HILOGE("The size of channels conflicts with channelNumber, size:%{public}d", size);
108         return ERROR;
109     }
110     int32_t parseDuration = 0;
111     for (int32_t i = 0; i < size; i++) {
112         cJSON *channelItem = parser.GetArrayItem(channelsItem, i);
113         CHKPR(channelItem, ERROR);
114         cJSON *channelParametersItem = parser.GetObjectItem(channelItem, "Parameters");
115         CHKPR(channelParametersItem, ERROR);
116         int32_t ret = ParseChannelParameters(parser, channelParametersItem);
117         CHKCR((ret == SUCCESS), ERROR, "parse channel parameters fail");
118         cJSON *patternItem = parser.GetObjectItem(channelItem, "Pattern");
119         CHKPR(patternItem, ERROR);
120         ret = ParsePattern(parser, patternItem, originPattern);
121         parseDuration += originPattern.patternDuration;
122         CHKCR((ret == SUCCESS), ERROR, "parse pattern fail");
123     }
124     patternPackage.packageDuration = parseDuration;
125     std::sort(originPattern.events.begin(), originPattern.events.end());
126     return SUCCESS;
127 }
128 
ParseChannelParameters(const JsonParser & parser,cJSON * channelParametersItem)129 int32_t DefaultVibratorDecoder::ParseChannelParameters(const JsonParser &parser,
130     cJSON *channelParametersItem) __attribute__((no_sanitize("cfi")))
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