• 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)
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, cJSON *channelParametersItem)
130 {
131     cJSON *indexItem = parser.GetObjectItem(channelParametersItem, "Index");
132     CHKPR(indexItem, ERROR);
133     int32_t indexVal = parser.GetIntValue(indexItem);
134     CHKCR((indexVal >= 0) && (indexVal < SUPPORT_CHANNEL_NUMBER), ERROR, "invalid channel index");
135     return SUCCESS;
136 }
137 
ParsePattern(const JsonParser & parser,cJSON * patternItem,VibratePattern & originPattern)138 int32_t DefaultVibratorDecoder::ParsePattern(const JsonParser &parser, cJSON *patternItem,
139     VibratePattern &originPattern)
140 {
141     if (!parser.IsArray(patternItem)) {
142         MISC_HILOGE("The value of pattern is not array");
143         return ERROR;
144     }
145     int32_t size = parser.GetArraySize(patternItem);
146     if (size > EVENT_NUM_MAX) {
147         MISC_HILOGE("The size of pattern is out of bounds, size:%{public}d", size);
148         return ERROR;
149     }
150     int32_t vibratorDuration = 0;
151     for (int32_t i = 0; i < size; i++) {
152         cJSON *item = parser.GetArrayItem(patternItem, i);
153         CHKPR(item, ERROR);
154         cJSON *eventItem = parser.GetObjectItem(item, "Event");
155         CHKPR(eventItem, ERROR);
156         VibrateEvent event;
157         int32_t ret = ParseEvent(parser, eventItem, event);
158         CHKCR((ret == SUCCESS), ERROR, "parse event fail");
159         vibratorDuration += event.duration;
160         originPattern.events.emplace_back(event);
161     }
162     originPattern.patternDuration = vibratorDuration;
163     return SUCCESS;
164 }
165 
ParseEvent(const JsonParser & parser,cJSON * eventItem,VibrateEvent & event)166 int32_t DefaultVibratorDecoder::ParseEvent(const JsonParser &parser, cJSON *eventItem, VibrateEvent &event)
167 {
168     cJSON *typeItem = parser.GetObjectItem(eventItem, "Type");
169     CHKPR(typeItem, ERROR);
170     std::string curType = parser.GetStringValue(typeItem);
171     if (curType == "continuous") {
172         event.tag = EVENT_TAG_CONTINUOUS;
173         cJSON *durationItem = parser.GetObjectItem(eventItem, "Duration");
174         CHKPR(durationItem, ERROR);
175         event.duration = parser.GetIntValue(durationItem);
176     } else if (curType == "transient") {
177         event.tag = EVENT_TAG_TRANSIENT;
178         event.duration = TRANSIENT_VIBRATION_DURATION;
179     } else {
180         MISC_HILOGE("Unknown event type, curType:%{public}s", curType.c_str());
181         return ERROR;
182     }
183     cJSON *startTimeItem = parser.GetObjectItem(eventItem, "StartTime");
184     CHKPR(startTimeItem, ERROR);
185     event.time = parser.GetIntValue(startTimeItem);
186     cJSON *eventParametersItem = parser.GetObjectItem(eventItem, "Parameters");
187     CHKPR(eventParametersItem, ERROR);
188     cJSON *intensityItem = parser.GetObjectItem(eventParametersItem, "Intensity");
189     CHKPR(intensityItem, ERROR);
190     event.intensity = parser.GetIntValue(intensityItem);
191     cJSON *frequencyItem = parser.GetObjectItem(eventParametersItem, "Frequency");
192     CHKPR(frequencyItem, ERROR);
193     event.frequency = parser.GetIntValue(frequencyItem);
194     if (!CheckEventParameters(event)) {
195         MISC_HILOGE("Parameter check of vibration event failed, startTime:%{public}d", event.time);
196         return ERROR;
197     }
198     if ((curType == "continuous") && parser.HasObjectItem(eventParametersItem, "Curve")) {
199         cJSON *curveItem = parser.GetObjectItem(eventParametersItem, "Curve");
200         CHKPR(curveItem, ERROR);
201         int32_t ret = ParseCurve(parser, curveItem, event);
202         if (ret != SUCCESS) {
203             MISC_HILOGE("Parse curve fail, startTime:%{public}d", event.time);
204             return ERROR;
205         }
206     }
207     return SUCCESS;
208 }
209 
CheckEventParameters(const VibrateEvent & event)210 bool DefaultVibratorDecoder::CheckEventParameters(const VibrateEvent &event)
211 {
212     if (event.time < STARTTMIE_MIN || event.time > STARTTMIE_MAX) {
213         MISC_HILOGE("The event startTime is out of range, startTime:%{public}d", event.time);
214         return false;
215     }
216     if (event.duration < CONTINUOUS_VIBRATION_DURATION_MIN ||
217         event.duration > CONTINUOUS_VIBRATION_DURATION_MAX) {
218         MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration);
219         return false;
220     }
221     if (event.intensity < INTENSITY_MIN || event.intensity > INTENSITY_MAX) {
222         MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity);
223         return false;
224     }
225     if (event.frequency < FREQUENCY_MIN || event.frequency > FREQUENCY_MAX) {
226         MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency);
227         return false;
228     }
229     return true;
230 }
231 
ParseCurve(const JsonParser & parser,cJSON * curveItem,VibrateEvent & event)232 int32_t DefaultVibratorDecoder::ParseCurve(const JsonParser &parser, cJSON *curveItem, VibrateEvent &event)
233 {
234     if (!parser.IsArray(curveItem)) {
235         MISC_HILOGE("The value of curve is not array");
236         return ERROR;
237     }
238     size_t size = static_cast<size_t>(parser.GetArraySize(curveItem));
239     if ((size < CURVE_POINT_MIN) || (size > CURVE_POINT_MAX)) {
240         MISC_HILOGE("The size of curve point is out of bounds, size:%{public}zu", size);
241         return ERROR;
242     }
243     for (size_t i = 0; i < size; i++) {
244         VibrateCurvePoint point;
245         cJSON *item = parser.GetArrayItem(curveItem, i);
246         CHKPR(item, ERROR);
247         cJSON *timeItem = parser.GetObjectItem(item, "Time");
248         CHKPR(timeItem, ERROR);
249         point.time = parser.GetIntValue(timeItem);
250         if ((point.time < 0) || (point.time > event.duration)) {
251             MISC_HILOGE("The time of curve point is out of bounds, time:%{public}d", point.time);
252             return ERROR;
253         }
254         cJSON *intensityItem = parser.GetObjectItem(item, "Intensity");
255         CHKPR(intensityItem, ERROR);
256         point.intensity = (parser.GetDoubleValue(intensityItem)) * CURVE_INTENSITY_SCALE;
257         if ((point.intensity < CURVE_INTENSITY_MIN) || (point.intensity > CURVE_INTENSITY_MAX)) {
258             MISC_HILOGE("The intensity of curve point is out of bounds, intensity:%{public}d", point.intensity);
259             return ERROR;
260         }
261         cJSON *frequencyItem = parser.GetObjectItem(item, "Frequency");
262         CHKPR(frequencyItem, ERROR);
263         point.frequency = parser.GetIntValue(frequencyItem);
264         if ((point.frequency < CURVE_FREQUENCY_MIN) || (point.frequency > CURVE_FREQUENCY_MAX)) {
265             MISC_HILOGE("The frequency of curve point is out of bounds, frequency:%{public}d", point.frequency);
266             return ERROR;
267         }
268         event.points.emplace_back(point);
269     }
270     std::sort(event.points.begin(), event.points.end());
271     return SUCCESS;
272 }
273 
PatternSplit(VibratePattern & originPattern,VibratePackage & patternPackage)274 void DefaultVibratorDecoder::PatternSplit(VibratePattern &originPattern,
275     VibratePackage &patternPackage) __attribute__((no_sanitize("cfi")))
276 {
277     if (originPattern.events.empty()) {
278         MISC_HILOGI("The origin pattern is empty");
279         return;
280     }
281     VibratePattern slicePattern;
282     slicePattern.startTime = originPattern.events[0].time;
283     size_t size = originPattern.events.size();
284     for (size_t i = 0; i < size; ++i) {
285         originPattern.events[i].time -= slicePattern.startTime;
286         slicePattern.events.emplace_back(originPattern.events[i]);
287         if ((slicePattern.events.size() >= PATTERN_CAPACITY) || (i == (size - 1))) {
288             patternPackage.patterns.emplace_back(slicePattern);
289             slicePattern.events.clear();
290             slicePattern.startTime = ((i < size - 1) ? originPattern.events[i + 1].time : 0);
291         }
292     }
293 }
294 } // namespace Sensors
295 } // namespace OHOS