• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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