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