1 /*
2 * Copyright (c) 2025 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 <climits>
17 #include <cstdlib>
18 #include <fcntl.h>
19 #include <gtest/gtest.h>
20 #include <set>
21 #include <string>
22 #include <thread>
23
24
25 #include "accesstoken_kit.h"
26 #include "nativetoken_kit.h"
27 #include "parameters.h"
28 #include "parcel.h"
29 #include "securec.h"
30 #include "sensors_errors.h"
31 #include "token_setproc.h"
32 #include "vibrator_agent.h"
33 #include "vibrator_agent_type.h"
34 #include "vibrator_infos.h"
35
36 #undef LOG_TAG
37 #define LOG_TAG "VibratorAgentSeekTest"
38
39 namespace OHOS {
40 namespace Sensors {
41 using namespace testing::ext;
42 using namespace Security::AccessToken;
43 using Security::AccessToken::AccessTokenID;
44
45 namespace {
46 constexpr int32_t CONT_TYPE_NO_CURVE_EVENT_IDX_9 = 9;
47 constexpr int32_t CONT_TYPE_NO_CURVE_EVENT_IDX_10 = 10;
48 constexpr int32_t CONT_TYPE_CURVE_EVENT_IDX_8 = 8;
49 constexpr int32_t CONT_TYPE_CURVE_EVENT_IDX_9 = 9;
50 constexpr int32_t CONT_TYPE_CURVE_EVENT_IDX_10 = 10;
51 constexpr int32_t FADE_IN_IDX_0 = 0;
52 constexpr int32_t FADE_IN_IDX_1 = 1;
53 constexpr int32_t FADE_OUT_IDX_10 = 10;
54 constexpr int32_t FADE_IN_FADE_OUT_DURATION = 1200;
55 constexpr int32_t MOD_NON_CONT_TYPE_EVENT_IDX = 0;
56 constexpr int32_t INVALID_FD = -1;
57 constexpr int32_t TRANSIENT_VIBRATION_DURATION = 48;
58 constexpr int32_t TIME_WAIT_FOR_OP = 2000;
59 constexpr int32_t TIME_WAIT_FOR_EACH_CASE = 200;
60 constexpr int32_t TEST_SUCCESS = 0;
61 constexpr int32_t TEST_FAILED = -1;
62 constexpr AccessTokenID INVALID_TOKEN_ID = 0;
63 }
64
65 PermissionStateFull g_infoManagerTestState = {
66 .grantFlags = {1},
67 .grantStatus = {PermissionState::PERMISSION_GRANTED},
68 .isGeneral = true,
69 .permissionName = "ohos.permission.VIBRATE",
70 .resDeviceID = {"local"}
71 };
72
73 HapPolicyParams g_infoManagerTestPolicyPrams = {
74 .apl = APL_NORMAL,
75 .domain = "test.domain",
76 .permList = {},
77 .permStateList = {g_infoManagerTestState}
78 };
79
80 HapInfoParams g_infoManagerTestInfoParms = {
81 .bundleName = "vibratoragentmodulation_test",
82 .userID = 1,
83 .instIndex = 0,
84 .appIDDesc = "vibratorAgentModulationTest"
85 };
86
87 class VibratorAgentModulationTest : public testing::Test {
88 public:
89 static void SetUpTestCase();
90 static void TearDownTestCase();
91 void SetUp();
92 void TearDown();
93 static AccessTokenID tokenID_;
94 };
95
96 AccessTokenID VibratorAgentModulationTest::tokenID_ = 0;
97
SetUpTestCase()98 void VibratorAgentModulationTest::SetUpTestCase()
99 {
100 AccessTokenIDEx tokenIdEx = {0};
101 tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, g_infoManagerTestPolicyPrams);
102 tokenID_ = tokenIdEx.tokenIdExStruct.tokenID;
103 if (tokenID_ != 0) {
104 MISC_HILOGI("acquire token successfully");
105 ASSERT_EQ(0, SetSelfTokenID(tokenID_));
106 }
107 MISC_HILOGE("failed to acquire token");
108 }
109
TearDownTestCase()110 void VibratorAgentModulationTest::TearDownTestCase()
111 {
112 int32_t ret = AccessTokenKit::DeleteToken(tokenID_);
113 if (tokenID_ != 0) {
114 ASSERT_EQ(RET_SUCCESS, ret);
115 }
116 }
117
SetUp()118 void VibratorAgentModulationTest::SetUp()
119 {
120 }
121
TearDown()122 void VibratorAgentModulationTest::TearDown()
123 {
124 std::this_thread::sleep_for(std::chrono::milliseconds(TIME_WAIT_FOR_EACH_CASE));
125 }
126
PlayModulatedPattern(const VibratorPackage & package)127 int32_t PlayModulatedPattern(const VibratorPackage& package)
128 {
129 VibratorIdentifier identifier = {
130 .deviceId = -1,
131 .vibratorId = -1,
132 };
133 bool isSupport = IsSupportVibratorCustomEnhanced(identifier);
134 if (!isSupport) {
135 MISC_HILOGI("PlayModulatedPattern: enhanced not supported");
136 return TEST_SUCCESS;
137 } else {
138 MISC_HILOGI("PlayModulatedPattern: enhanced is supported");
139 }
140 if (!SetUsageEnhanced(identifier, USAGE_UNKNOWN)) {
141 return TEST_FAILED;
142 }
143 for (int32_t idx = 0; idx < package.patternNum; idx++) {
144 int32_t res = PlayPatternEnhanced(identifier, package.patterns[0]);
145 std::this_thread::sleep_for(std::chrono::milliseconds(TIME_WAIT_FOR_OP));
146 CancelEnhanced(identifier);
147 if (res != TEST_SUCCESS) {
148 return TEST_FAILED;
149 }
150 }
151 return TEST_SUCCESS;
152 }
153 // this print function required when debugging failure of testcase
PrintVibratorPackageInfo(const VibratorPackage & package,const std::string & functionName)154 void PrintVibratorPackageInfo(const VibratorPackage& package, const std::string& functionName)
155 {
156 MISC_HILOGI("FunctionName:%{public}s data, package patternNum:%{public}d, package packageDuration:%{public}d",
157 functionName.c_str(), package.patternNum, package.packageDuration);
158 for (int32_t i = 0; i < package.patternNum; i++) {
159 MISC_HILOGI("FunctionName:%{public}s data, pattern time:%{public}d, pattern patternDuration:%{public}d,"
160 "pattern eventNum:%{public}d", functionName.c_str(), package.patterns[i].time,
161 package.patterns[i].patternDuration, package.patterns[i].eventNum);
162 for (int32_t j = 0; j < package.patterns[i].eventNum; j++) {
163 MISC_HILOGI("FunctionName:%{public}s data, event type:%{public}d, event time:%{public}d, "
164 "event duration:%{public}d, intensity:%{public}d, frequency:%{public}d, index:%{public}d, "
165 "pointNum:%{public}d", functionName.c_str(),
166 static_cast<int32_t>(package.patterns[i].events[j].type),
167 package.patterns[i].events[j].time, package.patterns[i].events[j].duration,
168 package.patterns[i].events[j].intensity, package.patterns[i].events[j].frequency,
169 package.patterns[i].events[j].index, package.patterns[i].events[j].pointNum);
170 for (int32_t k = 0; k < package.patterns[i].events[j].pointNum; k++) {
171 MISC_HILOGI("FunctionName:%{public}s data, points time:%{public}d, points intensity:%{public}d, "
172 "points frequency:%{public}d", functionName.c_str(),
173 package.patterns[i].events[j].points[k].time,
174 package.patterns[i].events[j].points[k].intensity,
175 package.patterns[i].events[j].points[k].frequency);
176 }
177 }
178 }
179 }
180
FreeEvent(VibratorEvent & event)181 void FreeEvent(VibratorEvent& event)
182 {
183 if (event.pointNum != 0 && event.points != nullptr) {
184 free(event.points);
185 event.points = nullptr;
186 }
187 }
188
IsVibratorCurvePointIdentical(const VibratorCurvePoint & first,const VibratorCurvePoint & second)189 bool IsVibratorCurvePointIdentical(const VibratorCurvePoint& first, const VibratorCurvePoint& second)
190 {
191 return first.frequency == second.frequency && first.intensity == second.intensity && first.time == second.time;
192 }
193
IsEventIdentical(const VibratorEvent & first,const VibratorEvent & second)194 bool IsEventIdentical(const VibratorEvent& first, const VibratorEvent& second)
195 {
196 if (first.type != second.type || first.time != second.time || first.duration != second.duration ||
197 first.intensity != second.intensity || first.frequency != second.frequency || first.index != second.index ||
198 first.pointNum != second.pointNum) {
199 return false;
200 }
201 if (first.type != EVENT_TYPE_CONTINUOUS) {
202 return first.pointNum == 0;
203 }
204 if (first.pointNum == 0) {
205 return true;
206 }
207 const VibratorCurvePoint* firstCurve = first.points;
208 const VibratorCurvePoint* secondCurve = second.points;
209 if (firstCurve == nullptr || secondCurve == nullptr) {
210 return false;
211 }
212 for (int32_t idx = 0; idx < first.pointNum; idx++) {
213 if (!IsVibratorCurvePointIdentical(firstCurve[idx], secondCurve[idx])) {
214 return false;
215 }
216 }
217 return true;
218 }
219
IsPatternIdentical(const VibratorPattern & first,const VibratorPattern & second)220 bool IsPatternIdentical(const VibratorPattern& first, const VibratorPattern& second)
221 {
222 if (first.time != second.time || first.eventNum != second.eventNum ||
223 first.patternDuration != second.patternDuration) {
224 return false;
225 }
226 for (int32_t idx = 0; idx < first.eventNum; idx++) {
227 if (!IsEventIdentical(first.events[idx], second.events[idx])) {
228 return false;
229 }
230 }
231 return true;
232 }
233
IsPackageIdentical(const VibratorPackage & first,const VibratorPackage & second)234 bool IsPackageIdentical(const VibratorPackage& first, const VibratorPackage& second)
235 {
236 if (first.patternNum != second.patternNum || first.packageDuration != second.packageDuration) {
237 return false;
238 }
239 for (int32_t idx = 0; idx < first.patternNum; idx++) {
240 if (!IsPatternIdentical(first.patterns[idx], second.patterns[idx])) {
241 return false;
242 }
243 }
244 return true;
245 }
246
GetFdWithRealpath(const char * path)247 int GetFdWithRealpath(const char* path)
248 {
249 char filePath[PATH_MAX];
250 char *resolvedPath = realpath(path, filePath);
251 if (resolvedPath == nullptr) {
252 MISC_HILOGE("GetFdWithRealpath: invalid path %{public}s", path);
253 return INVALID_FD;
254 }
255 int fd = open(filePath, O_RDONLY);
256 if (fd < 0) {
257 MISC_HILOGE("GetFdWithRealpath: failed to open %{public}s", filePath);
258 return INVALID_FD;
259 }
260 return fd;
261 }
262
ConvertFileToVibratorPackage(const char * functionName,const char * filePath,VibratorPackage & vibratorPackage)263 bool ConvertFileToVibratorPackage(const char* functionName, const char* filePath, VibratorPackage& vibratorPackage)
264 {
265 MISC_HILOGI("ConvertFileToVibratorPackage in: %{public}s", functionName);
266 int fd = GetFdWithRealpath(filePath);
267 if (fd < 0) {
268 MISC_HILOGI("ConvertFileToVibratorPackage: failed to open %{public}s in: %{public}s", filePath, functionName);
269 return false;
270 }
271 MISC_HILOGD("fd:%{public}d", fd);
272 VibratorFileDescription vfd;
273 struct stat64 statbuf = { 0 };
274 if (fstat64(fd, &statbuf) != 0) {
275 MISC_HILOGE("failed to call fstat64 with param: %{public}s", filePath);
276 close(fd);
277 return false;
278 }
279 vfd.fd = fd;
280 vfd.offset = 0;
281 vfd.length = statbuf.st_size;
282 if (PreProcess(vfd, vibratorPackage) != 0) {
283 MISC_HILOGE("failed to call PreProcess with param: %{public}s", filePath);
284 close(fd);
285 return false;
286 }
287 PrintVibratorPackageInfo(vibratorPackage, std::string(functionName));
288 return true;
289 }
290
ConvertEventToParams(VibratorEvent & event,VibratorCurvePoint ** curvePointArg,int32_t & curvePointNum,int32_t & duration)291 void ConvertEventToParams(VibratorEvent& event, VibratorCurvePoint** curvePointArg,
292 int32_t& curvePointNum, int32_t& duration)
293 {
294 if (curvePointArg == nullptr) {
295 MISC_HILOGE("failed to ConvertEventToParams due to nullptr");
296 }
297 *curvePointArg = event.points;
298 curvePointNum = event.pointNum;
299 duration = event.duration + event.time;
300 for (int32_t idx = 0; idx < curvePointNum; idx++) {
301 (*curvePointArg)[idx].time += event.time;
302 }
303 }
304
GetExpectedEventInModulateNonContinuousType()305 VibratorEvent GetExpectedEventInModulateNonContinuousType()
306 {
307 return VibratorEvent{.type = EVENT_TYPE_TRANSIENT, .time = 0, .duration = TRANSIENT_VIBRATION_DURATION,
308 .intensity = 0, .frequency = 31, .index = 0, .pointNum = 0, .points = nullptr};
309 }
310
311 HWTEST_F(VibratorAgentModulationTest, ModulateNonContinuousType, TestSize.Level1)
312 {
313 MISC_HILOGI("ModulateNonContinuousType in");
314 VibratorPackage package;
315 VibratorPackage modulationPackage;
316 VibratorPackage packageAfterModulation;
317 ASSERT_TRUE(ConvertFileToVibratorPackage(
318 "ModulateNonContinuousType", "/data/test/vibrator/package_before_modulation.json", package));
319 ASSERT_TRUE(ConvertFileToVibratorPackage(
320 "ModulateNonContinuousType", "/data/test/vibrator/modulation_curve.json", modulationPackage));
321 ASSERT_TRUE(modulationPackage.patternNum >= 1);
322 ASSERT_TRUE(modulationPackage.patterns[0].eventNum >= 1);
323 ASSERT_NE(modulationPackage.patterns[0].events, nullptr);
324 VibratorCurvePoint* modulationCurve = nullptr;
325 int32_t curvePointNum = 0;
326 int32_t duration = 0;
327 ConvertEventToParams(modulationPackage.patterns[0].events[0], &modulationCurve, curvePointNum, duration);
328 ASSERT_EQ(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
329 ASSERT_EQ(package.patternNum, packageAfterModulation.patternNum);
330 ASSERT_EQ(package.packageDuration, packageAfterModulation.packageDuration);
331 const VibratorPattern& pattern = package.patterns[0];
332 const VibratorPattern& patternAfterMod = packageAfterModulation.patterns[0];
333 ASSERT_EQ(pattern.eventNum, patternAfterMod.eventNum);
334 for (int32_t eventIdx = 0; eventIdx < pattern.eventNum; eventIdx++) {
335 if (eventIdx == MOD_NON_CONT_TYPE_EVENT_IDX) {
336 VibratorEvent expectedEvent = GetExpectedEventInModulateNonContinuousType();
337 ASSERT_NE(expectedEvent.type, EVENT_TYPE_UNKNOWN);
338 ASSERT_TRUE(IsEventIdentical(expectedEvent, patternAfterMod.events[eventIdx]));
339 FreeEvent(expectedEvent);
340 } else {
341 ASSERT_TRUE(IsEventIdentical(pattern.events[eventIdx], patternAfterMod.events[eventIdx]));
342 }
343 }
344 if (tokenID_ != INVALID_TOKEN_ID) {
345 MISC_HILOGI("start to play modulated pattern");
346 ASSERT_EQ(PlayModulatedPattern(packageAfterModulation), TEST_SUCCESS);
347 } else {
348 MISC_HILOGW("unable to play modulated pattern due to privilege issue, skip");
349 }
350 ASSERT_EQ(FreeVibratorPackage(package), 0);
351 ASSERT_EQ(FreeVibratorPackage(packageAfterModulation), 0);
352 ASSERT_EQ(FreeVibratorPackage(modulationPackage), 0);
353 MISC_HILOGI("ModulateNonContinuousType end");
354 }
355
GetContinuousTypeWithCurvePointsExpectation()356 VibratorEvent GetContinuousTypeWithCurvePointsExpectation()
357 {
358 std::vector<VibratorCurvePoint> curveVec;
359 curveVec.emplace_back(VibratorCurvePoint{.time = 0, .intensity = 0, .frequency = -10});
360 curveVec.emplace_back(VibratorCurvePoint{.time = 100, .intensity = 17, .frequency = -10});
361 curveVec.emplace_back(VibratorCurvePoint{.time = 200, .intensity = 50, .frequency = 10});
362 curveVec.emplace_back(VibratorCurvePoint{.time = 254, .intensity = 0, .frequency = 20});
363 VibratorCurvePoint *curvePoints = (VibratorCurvePoint *)calloc(curveVec.size(), sizeof(VibratorCurvePoint));
364 if (curvePoints == nullptr) {
365 MISC_HILOGE("failed to allocate memory for VibratorCurvePoint");
366 curveVec.clear();
367 } else {
368 uint32_t copyBytesCount = curveVec.size() * sizeof(VibratorCurvePoint);
369 memcpy_s(curvePoints, copyBytesCount, curveVec.data(), copyBytesCount);
370 }
371 return VibratorEvent{.type = curvePoints == nullptr ? EVENT_TYPE_UNKNOWN : EVENT_TYPE_CONTINUOUS,
372 .time = 410, .duration = 254, .intensity = 38, .frequency = 30, .index = 0,
373 .pointNum = (int32_t)curveVec.size(), .points = curvePoints};
374 }
375
GetContinuousTypeWithoutCurvePointsExpectationForEvent(int32_t idx)376 VibratorEvent GetContinuousTypeWithoutCurvePointsExpectationForEvent(int32_t idx)
377 {
378 switch (idx) {
379 case CONT_TYPE_NO_CURVE_EVENT_IDX_9:
380 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 940, .duration = 160,
381 .intensity = 7, .frequency = 57, .index = 0, .pointNum = 0, .points = nullptr};
382 break;
383 case CONT_TYPE_NO_CURVE_EVENT_IDX_10:
384 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 1100, .duration = 100,
385 .intensity = 14, .frequency = 64, .index = 0, .pointNum = 0, .points = nullptr};
386 break;
387 default:
388 return VibratorEvent{.type = EVENT_TYPE_UNKNOWN, .time = -1, .duration = -1,
389 .intensity = -1, .frequency = -1, .index = 0, .pointNum = 0, .points = nullptr};
390 break;
391 }
392 }
393
394 HWTEST_F(VibratorAgentModulationTest, ContinuousTypeWithCurvePoint, TestSize.Level1)
395 {
396 MISC_HILOGI("ContinuousTypeWithCurvePoint in");
397 VibratorPackage package;
398 VibratorPackage modulationPackage;
399 VibratorPackage packageAfterModulation;
400 ASSERT_TRUE(ConvertFileToVibratorPackage(
401 "ContinuousTypeWithCurvePoint", "/data/test/vibrator/package_before_modulation.json", package));
402 ASSERT_TRUE(ConvertFileToVibratorPackage(
403 "ContinuousTypeWithCurvePoint", "/data/test/vibrator/modulation_curve.json", modulationPackage));
404 ASSERT_TRUE(modulationPackage.patternNum >= 1);
405 ASSERT_TRUE(modulationPackage.patterns[0].eventNum >= 1);
406 ASSERT_NE(modulationPackage.patterns[0].events, nullptr);
407 VibratorCurvePoint* modulationCurve = nullptr;
408 int32_t curvePointNum = 0;
409 int32_t duration = 0;
410 ConvertEventToParams(modulationPackage.patterns[0].events[1], &modulationCurve, curvePointNum, duration);
411 ASSERT_EQ(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
412 ASSERT_FALSE(IsPackageIdentical(package, packageAfterModulation));
413 ASSERT_EQ(packageAfterModulation.patternNum, package.patternNum);
414 ASSERT_EQ(packageAfterModulation.patterns[0].eventNum, package.patterns[0].eventNum);
415 const VibratorPattern& pattern = packageAfterModulation.patterns[0];
416 const VibratorPattern& originalPattern = package.patterns[0];
417 for (int32_t idx = 0; idx < pattern.eventNum; idx++) {
418 if (idx != 7) {
419 ASSERT_TRUE(IsEventIdentical(originalPattern.events[idx], pattern.events[idx]));
420 } else {
421 const VibratorEvent& afterModEvent = pattern.events[idx];
422 VibratorEvent expectedEvent = GetContinuousTypeWithCurvePointsExpectation();
423 ASSERT_NE(expectedEvent.type, EVENT_TYPE_UNKNOWN);
424 ASSERT_TRUE(IsEventIdentical(afterModEvent, expectedEvent));
425 FreeEvent(expectedEvent);
426 }
427 }
428 if (tokenID_ != INVALID_TOKEN_ID) {
429 MISC_HILOGI("start to play modulated pattern");
430 ASSERT_EQ(PlayModulatedPattern(packageAfterModulation), TEST_SUCCESS);
431 } else {
432 MISC_HILOGW("unable to play modulated pattern due to privilege issue, skip");
433 }
434 ASSERT_EQ(FreeVibratorPackage(package), 0);
435 ASSERT_EQ(FreeVibratorPackage(packageAfterModulation), 0);
436 ASSERT_EQ(FreeVibratorPackage(modulationPackage), 0);
437 MISC_HILOGI("ContinuousTypeWithCurvePoint end");
438 }
439
440 HWTEST_F(VibratorAgentModulationTest, ContinuousTypeWithoutCurvePoint, TestSize.Level1)
441 {
442 MISC_HILOGI("ContinuousTypeWithoutCurvePoint in");
443 VibratorPackage package, modulationPackage, packageAfterModulation;
444 ASSERT_TRUE(ConvertFileToVibratorPackage(
445 "ContinuousTypeWithoutCurvePoint", "/data/test/vibrator/package_before_modulation.json", package));
446 ASSERT_TRUE(ConvertFileToVibratorPackage(
447 "ContinuousTypeWithoutCurvePoint", "/data/test/vibrator/modulation_curve.json", modulationPackage));
448 ASSERT_TRUE(modulationPackage.patternNum >= 1);
449 ASSERT_TRUE(modulationPackage.patterns[0].eventNum >= 1);
450 ASSERT_NE(modulationPackage.patterns[0].events, nullptr);
451 VibratorCurvePoint* modulationCurve = nullptr;
452 int32_t curvePointNum = 0;
453 int32_t duration = 0;
454 ConvertEventToParams(modulationPackage.patterns[0].events[2], &modulationCurve, curvePointNum, duration);
455 ASSERT_EQ(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
456 ASSERT_FALSE(IsPackageIdentical(package, packageAfterModulation));
457 ASSERT_EQ(packageAfterModulation.patternNum, package.patternNum);
458 ASSERT_EQ(packageAfterModulation.patterns[0].eventNum, package.patterns[0].eventNum);
459 const VibratorPattern& pattern = packageAfterModulation.patterns[0];
460 const VibratorPattern& originalPattern = package.patterns[0];
461 for (int32_t idx = 0; idx < pattern.eventNum; idx++) {
462 if (idx != CONT_TYPE_NO_CURVE_EVENT_IDX_9 && idx != CONT_TYPE_NO_CURVE_EVENT_IDX_10) {
463 ASSERT_TRUE(IsEventIdentical(originalPattern.events[idx], pattern.events[idx]));
464 } else {
465 const VibratorEvent& event = pattern.events[idx];
466 VibratorEvent expectedEvent = GetContinuousTypeWithoutCurvePointsExpectationForEvent(idx);
467 ASSERT_TRUE(IsEventIdentical(event, expectedEvent));
468 FreeEvent(expectedEvent);
469 }
470 }
471 if (tokenID_ != INVALID_TOKEN_ID) {
472 MISC_HILOGI("start to play modulated pattern");
473 ASSERT_EQ(PlayModulatedPattern(packageAfterModulation), TEST_SUCCESS);
474 } else {
475 MISC_HILOGW("unable to play modulated pattern due to privilege issue, skip");
476 }
477 ASSERT_EQ(FreeVibratorPackage(package), 0);
478 ASSERT_EQ(FreeVibratorPackage(packageAfterModulation), 0);
479 ASSERT_EQ(FreeVibratorPackage(modulationPackage), 0);
480 MISC_HILOGI("ContinuousTypeWithoutCurvePoint end");
481 }
482
GetExpectedEventForContinuousTypeWithCurvePointAndEventStartTime(int idx)483 VibratorEvent GetExpectedEventForContinuousTypeWithCurvePointAndEventStartTime(int idx)
484 {
485 VibratorCurvePoint* curvePoints = nullptr;
486 std::vector<VibratorCurvePoint> pointsVec;
487 switch (idx) {
488 case CONT_TYPE_CURVE_EVENT_IDX_8:
489 pointsVec.emplace_back(VibratorCurvePoint{.time = 0, .intensity = 0, .frequency = 0});
490 pointsVec.emplace_back(VibratorCurvePoint{.time = 100, .intensity = 100, .frequency = 0});
491 pointsVec.emplace_back(VibratorCurvePoint{.time = 200, .intensity = 17, .frequency = -10});
492 pointsVec.emplace_back(VibratorCurvePoint{.time = 254, .intensity = 0, .frequency = -10});
493 curvePoints = (VibratorCurvePoint *)calloc(pointsVec.size(), sizeof(VibratorCurvePoint));
494 if (curvePoints == nullptr) {
495 MISC_HILOGE("failed to allocate memory for VibratorCurvePoint");
496 } else {
497 uint32_t copyBytesCount = pointsVec.size() * sizeof(VibratorCurvePoint);
498 memcpy_s(curvePoints, copyBytesCount, pointsVec.data(), copyBytesCount);
499 }
500 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 670, .duration = 254,
501 .intensity = 38, .frequency = 30, .index = 0,
502 .pointNum = curvePoints == nullptr ? 0 : (int32_t)pointsVec.size(), .points = curvePoints};
503 break;
504 case CONT_TYPE_CURVE_EVENT_IDX_9:
505 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 940, .duration = 160,
506 .intensity = 12, .frequency = 27, .index = 0, .pointNum = 0, .points = nullptr};
507 break;
508 case CONT_TYPE_CURVE_EVENT_IDX_10:
509 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 1100, .duration = 100,
510 .intensity = 18, .frequency = 64, .index = 0, .pointNum = 0, .points = nullptr};
511 break;
512 default:
513 return VibratorEvent{.type = EVENT_TYPE_UNKNOWN, .time = -1, .duration = -1, .intensity = -1,
514 .frequency = -1, .index = 0, .pointNum = 0, .points = nullptr};
515 break;
516 }
517 }
518
519 HWTEST_F(VibratorAgentModulationTest, ContinuousTypeWithCurvePointAndEventStartTime, TestSize.Level1)
520 {
521 MISC_HILOGI("ContinuousTypeWithCurvePointAndEventStartTime in");
522 VibratorPackage package;
523 VibratorPackage modulationPackage;
524 VibratorPackage packageAfterModulation;
525 ASSERT_TRUE(ConvertFileToVibratorPackage("ContinuousTypeWithCurvePointAndEventStartTime",
526 "/data/test/vibrator/package_before_modulation.json", package));
527 ASSERT_TRUE(ConvertFileToVibratorPackage("ContinuousTypeWithCurvePointAndEventStartTime",
528 "/data/test/vibrator/modulation_curve.json", modulationPackage));
529 ASSERT_TRUE(modulationPackage.patternNum >= 1);
530 ASSERT_TRUE(modulationPackage.patterns[0].eventNum >= 1);
531 ASSERT_NE(modulationPackage.patterns[0].events, nullptr);
532 VibratorEvent& modulationEvent = modulationPackage.patterns[0].events[1];
533 modulationEvent.duration = 270;
534 modulationEvent.time = 850;
535 VibratorCurvePoint* modulationCurve = nullptr;
536 int32_t curvePointNum = 0;
537 int32_t duration = 0;
538 ConvertEventToParams(modulationEvent, &modulationCurve, curvePointNum, duration);
539 ASSERT_EQ(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
540 ASSERT_FALSE(IsPackageIdentical(package, packageAfterModulation));
541 ASSERT_EQ(packageAfterModulation.patternNum, package.patternNum);
542 ASSERT_EQ(packageAfterModulation.patterns[0].eventNum, package.patterns[0].eventNum);
543 const VibratorPattern& pattern = packageAfterModulation.patterns[0];
544 const VibratorPattern& originalPattern = package.patterns[0];
545 for (int32_t idx = 0; idx < pattern.eventNum; idx++) {
546 if (idx < 8) {
547 ASSERT_TRUE(IsEventIdentical(originalPattern.events[idx], pattern.events[idx]));
548 } else {
549 const VibratorEvent& event = pattern.events[idx];
550 VibratorEvent expectedEvent = GetExpectedEventForContinuousTypeWithCurvePointAndEventStartTime(idx);
551 ASSERT_NE(expectedEvent.type, EVENT_TYPE_UNKNOWN);
552 ASSERT_TRUE(IsEventIdentical(event, expectedEvent));
553 FreeEvent(expectedEvent);
554 }
555 }
556 if (tokenID_ != INVALID_TOKEN_ID) {
557 MISC_HILOGI("start to play modulated pattern");
558 ASSERT_EQ(PlayModulatedPattern(packageAfterModulation), TEST_SUCCESS);
559 } else {
560 MISC_HILOGW("unable to play modulated pattern due to privilege issue, skip");
561 }
562 ASSERT_EQ(FreeVibratorPackage(package), 0);
563 ASSERT_EQ(FreeVibratorPackage(packageAfterModulation), 0);
564 ASSERT_EQ(FreeVibratorPackage(modulationPackage), 0);
565 MISC_HILOGI("ContinuousTypeWithCurvePointAndEventStartTime end");
566 }
567
568 HWTEST_F(VibratorAgentModulationTest, InvalidModulationEvent, TestSize.Level1)
569 {
570 MISC_HILOGI("InvalidModulationEvent in");
571 VibratorPackage package;
572 VibratorPackage packageAfterModulation;
573 ASSERT_TRUE(ConvertFileToVibratorPackage("InvalidModulationEvent",
574 "/data/test/vibrator/package_before_modulation.json", package));
575 ASSERT_NE(ModulatePackage(nullptr, -1, 220, package, packageAfterModulation), 0);
576 ASSERT_EQ(FreeVibratorPackage(package), 0);
577 MISC_HILOGI("InvalidModulationEvent end");
578 }
579
580 HWTEST_F(VibratorAgentModulationTest, EventWithInvalidAmountOfPoints, TestSize.Level1)
581 {
582 MISC_HILOGI("EventWithInvalidAmountOfPoints in");
583 VibratorPackage package;
584 VibratorPackage modulationPackage;
585 VibratorPackage packageAfterModulation;
586 ASSERT_TRUE(ConvertFileToVibratorPackage("ContinuousTypeWithCurvePointAndEventStartTime",
587 "/data/test/vibrator/package_before_modulation.json", package));
588 ASSERT_TRUE(ConvertFileToVibratorPackage("ContinuousTypeWithCurvePointAndEventStartTime",
589 "/data/test/vibrator/modulation_curve.json", modulationPackage));
590 VibratorEvent& modulationEvent = modulationPackage.patterns[0].events[1];
591 VibratorCurvePoint* modulationCurve = nullptr;
592 int32_t curvePointNum = 0;
593 int32_t duration = 0;
594 package.patterns[0].events[8].pointNum = 2;
595 ConvertEventToParams(modulationEvent, &modulationCurve, curvePointNum, duration);
596 ASSERT_NE(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
597 ASSERT_EQ(FreeVibratorPackage(package), 0);
598 ASSERT_EQ(FreeVibratorPackage(modulationPackage), 0);
599 MISC_HILOGI("EventWithInvalidAmountOfPoints end");
600 }
601
GenerateFadeInFadeOutCurve(VibratorCurvePoint ** modulationCurve,int32_t & curvePointNum,int32_t & duration)602 bool GenerateFadeInFadeOutCurve(VibratorCurvePoint** modulationCurve, int32_t& curvePointNum, int32_t& duration)
603 {
604 if (modulationCurve == nullptr) {
605 MISC_HILOGI("Invalid pointer for modulationCurve");
606 return false;
607 }
608 std::vector<VibratorCurvePoint> curveVec {
609 VibratorCurvePoint{.time = 0, .intensity = 0, .frequency = 0},
610 VibratorCurvePoint{.time = 20, .intensity = 30, .frequency = 0},
611 VibratorCurvePoint{.time = 40, .intensity = 50, .frequency = 0},
612 VibratorCurvePoint{.time = 70, .intensity = 70, .frequency = 0},
613 VibratorCurvePoint{.time = 90, .intensity = 100, .frequency = 0},
614 VibratorCurvePoint{.time = 1000, .intensity = 90, .frequency = 0},
615 VibratorCurvePoint{.time = 1120, .intensity = 70, .frequency = 0},
616 VibratorCurvePoint{.time = 1150, .intensity = 50, .frequency = 0},
617 VibratorCurvePoint{.time = 1170, .intensity = 30, .frequency = 0},
618 VibratorCurvePoint{.time = 1200, .intensity = 0, .frequency = 0}
619 };
620 VibratorCurvePoint* curve = (VibratorCurvePoint*)malloc(curveVec.size() * sizeof(VibratorCurvePoint));
621 if (curve == nullptr) {
622 MISC_HILOGI("generateFadeInFadeOutCurve: failed to allocate memory for curve");
623 return false;
624 }
625 std::copy(curveVec.begin(), curveVec.end(), curve);
626 *modulationCurve = curve;
627 curvePointNum = (int32_t)curveVec.size();
628 duration = FADE_IN_FADE_OUT_DURATION;
629 return true;
630 }
631
GetExpectedOutputEventsForFadeInFadeOut(int32_t idx)632 VibratorEvent GetExpectedOutputEventsForFadeInFadeOut(int32_t idx)
633 {
634 VibratorCurvePoint* curvePoints = nullptr;
635 std::vector<VibratorCurvePoint> curveVec;
636 switch (idx) {
637 case FADE_IN_IDX_0:
638 return VibratorEvent{.type = EVENT_TYPE_TRANSIENT, .time = 0, .duration = TRANSIENT_VIBRATION_DURATION,
639 .intensity = 0, .frequency = 31, .index = 0, .pointNum = 0, .points = nullptr};
640 break;
641 case FADE_IN_IDX_1:
642 curveVec.emplace_back(VibratorCurvePoint{.time = 0, .intensity = 0, .frequency = 0});
643 curveVec.emplace_back(VibratorCurvePoint{.time = 1, .intensity = 50, .frequency = 0});
644 curveVec.emplace_back(VibratorCurvePoint{.time = 40, .intensity = 70, .frequency = 0});
645 curveVec.emplace_back(VibratorCurvePoint{.time = 54, .intensity = 0, .frequency = 0});
646 curvePoints = (VibratorCurvePoint *)calloc(curveVec.size(), sizeof(VibratorCurvePoint));
647 if (curvePoints == nullptr) {
648 MISC_HILOGE("failed to allocate memory for VibratorCurvePoint");
649 curveVec.clear();
650 } else {
651 uint32_t copyBytesCount = curveVec.size() * sizeof(VibratorCurvePoint);
652 memcpy_s(curvePoints, copyBytesCount, curveVec.data(), copyBytesCount);
653 }
654 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 40, .duration = 54,
655 .intensity = 38, .frequency = 30, .index = 0, .pointNum = (int32_t)curveVec.size(),
656 .points = curvePoints};
657 break;
658 case FADE_OUT_IDX_10:
659 return VibratorEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 1100, .duration = 100,
660 .intensity = 21, .frequency = 44, .index = 0, .pointNum = 0, .points = nullptr};
661 break;
662 default:
663 return VibratorEvent{.type = EVENT_TYPE_UNKNOWN, .time = -1, .duration = -1, .intensity = -1,
664 .frequency = -1, .index = 0, .pointNum = 0, .points = nullptr};
665 break;
666 }
667 }
668
669 HWTEST_F(VibratorAgentModulationTest, FadeInFadeOut, TestSize.Level1)
670 {
671 MISC_HILOGI("FadeInFadeOut in");
672 VibratorCurvePoint* modulationCurve;
673 int32_t curvePointNum;
674 int32_t duration;
675 ASSERT_TRUE(GenerateFadeInFadeOutCurve(&modulationCurve, curvePointNum, duration));
676 VibratorPackage package;
677 VibratorPackage packageAfterModulation;
678 ASSERT_TRUE(ConvertFileToVibratorPackage("FadeInFadeOut",
679 "/data/test/vibrator/package_before_modulation.json", package));
680 ASSERT_EQ(ModulatePackage(modulationCurve, curvePointNum, duration, package, packageAfterModulation), 0);
681 const VibratorPattern& originalPattern = package.patterns[0];
682 const VibratorPattern& afterModPattern = packageAfterModulation.patterns[0];
683 std::set<int32_t> modifiedEventIdx = {FADE_IN_IDX_0, FADE_IN_IDX_1, FADE_OUT_IDX_10};
684 std::set<VibratorCurvePoint> expectedOuput;
685 for (int32_t eventIdx = 0; eventIdx < originalPattern.eventNum; eventIdx++) {
686 if (modifiedEventIdx.find(eventIdx) == modifiedEventIdx.end()) {
687 ASSERT_TRUE(IsEventIdentical(originalPattern.events[eventIdx], afterModPattern.events[eventIdx]));
688 } else {
689 const VibratorEvent& afterModEvent = afterModPattern.events[eventIdx];
690 VibratorEvent expectedEvent = GetExpectedOutputEventsForFadeInFadeOut(eventIdx);
691 ASSERT_NE(expectedEvent.type, EVENT_TYPE_UNKNOWN);
692 ASSERT_TRUE(IsEventIdentical(afterModEvent, expectedEvent));
693 FreeEvent(expectedEvent);
694 }
695 }
696 if (tokenID_ != INVALID_TOKEN_ID) {
697 MISC_HILOGI("start to play modulated pattern");
698 ASSERT_EQ(PlayModulatedPattern(packageAfterModulation), TEST_SUCCESS);
699 } else {
700 MISC_HILOGW("unable to play modulated pattern due to privilege issue, skip");
701 }
702 ASSERT_EQ(FreeVibratorPackage(package), 0);
703 ASSERT_EQ(FreeVibratorPackage(packageAfterModulation), 0);
704 free(modulationCurve);
705 modulationCurve = nullptr;
706 MISC_HILOGI("FadeInFadeOut end");
707 }
708
709 } // namespace Sensors
710 } // namespace OHOS
711