1 /*
2  * Copyright (c) 2024 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 "vibrator_ffi.h"
17 
18 #include <map>
19 #include <set>
20 #include <string>
21 
22 #include "file_utils.h"
23 #include "miscdevice_log.h"
24 #include "sensors_errors.h"
25 #include "vibrator_agent.h"
26 
27 #undef LOG_TAG
28 #define LOG_TAG "Vibrator-Cj"
29 
30 namespace OHOS {
31 namespace Sensors {
32 static std::map<std::string, int32_t> g_usageType = {
33     {"unknown", USAGE_UNKNOWN},
34     {"alarm", USAGE_ALARM},
35     {"ring", USAGE_RING},
36     {"notification", USAGE_NOTIFICATION},
37     {"communication", USAGE_COMMUNICATION},
38     {"touch", USAGE_TOUCH},
39     {"media", USAGE_MEDIA},
40     {"physicalFeedback", USAGE_PHYSICAL_FEEDBACK},
41     {"simulateReality", USAGE_SIMULATE_REALITY},
42 };
43 
44 static std::set<std::string> g_allowedTypes = {"time", "preset", "file", "pattern"};
45 struct CJVibrateInfo {
46     std::string type;
47     std::string usage;
48     bool systemUsage;
49     int32_t duration = 0;
50     std::string effectId;
51     int32_t count = 0;
52     int32_t fd = -1;
53     int64_t offset = 0;
54     int64_t length = -1;
55     int32_t intensity = 0;
56     VibratorPattern vibratorPattern;
57 };
58 
SetUsage(const std::string &usage, bool systemUsage)59 bool SetUsage(const std::string &usage, bool systemUsage)
60 {
61     if (auto iter = g_usageType.find(usage); iter == g_usageType.end()) {
62         MISC_HILOGE("Wrong usage type");
63         return false;
64     }
65     return SetUsage(g_usageType[usage], systemUsage);
66 }
67 
StartVibrate(const CJVibrateInfo &info)68 int32_t StartVibrate(const CJVibrateInfo &info)
69 {
70     CALL_LOG_ENTER;
71     if (!SetUsage(info.usage, info.systemUsage)) {
72         MISC_HILOGE("SetUsage fail");
73         return PARAMETER_ERROR;
74     }
75     if (g_allowedTypes.find(info.type) == g_allowedTypes.end()) {
76         MISC_HILOGE("Invalid vibrate type, type:%{public}s", info.type.c_str());
77         return PARAMETER_ERROR;
78     }
79     if (info.type == "preset") {
80         if (!SetLoopCount(info.count)) {
81             MISC_HILOGE("SetLoopCount fail");
82             return PARAMETER_ERROR;
83         }
84         return PlayPrimitiveEffect(info.effectId.c_str(), info.intensity);
85     } else if (info.type == "file") {
86         return PlayVibratorCustom(info.fd, info.offset, info.length);
87     } else if (info.type == "pattern") {
88         return PlayPattern(info.vibratorPattern);
89     }
90     return StartVibratorOnce(info.duration);
91 }
92 
93 extern "C" {
FfiVibratorStartVibrationTime(RetVibrateTime effect, RetVibrateAttribute attribute, int32_t &code)94     void FfiVibratorStartVibrationTime(RetVibrateTime effect, RetVibrateAttribute attribute, int32_t &code)
95     {
96         CJVibrateInfo info;
97         std::string strType(effect.timeType);
98         info.type = strType;
99         info.duration = effect.duration;
100         std::string strUsage(attribute.usage);
101         info.usage = strUsage;
102         info.systemUsage = false;
103         code = StartVibrate(info);
104     };
105 
FfiVibratorStartVibrationPreset(RetVibratePreset effect, RetVibrateAttribute attribute, int32_t &code)106     void FfiVibratorStartVibrationPreset(RetVibratePreset effect, RetVibrateAttribute attribute, int32_t &code)
107     {
108         CJVibrateInfo info;
109         std::string strType(effect.presetType);
110         info.type = strType;
111         std::string strEffectId(effect.effectId);
112         info.effectId = strEffectId;
113         info.count = effect.count;
114         info.intensity = effect.intensity;
115         std::string strUsage(attribute.usage);
116         info.usage = strUsage;
117         info.systemUsage = false;
118         code = StartVibrate(info);
119     };
120 
FfiVibratorStartVibrationFile(RetVibrateFromFile effect, RetVibrateAttribute attribute, int32_t &code)121     void FfiVibratorStartVibrationFile(RetVibrateFromFile effect, RetVibrateAttribute attribute, int32_t &code)
122     {
123         CJVibrateInfo info;
124         std::string strType(effect.fileType);
125         info.type = strType;
126         info.fd = effect.hapticFd.fd;
127         info.offset = effect.hapticFd.offSet;
128         info.length = effect.hapticFd.length;
129         std::string strUsage(attribute.usage);
130         info.usage = strUsage;
131         info.systemUsage = false;
132         code = StartVibrate(info);
133     };
134 
FfiVibratorStopVibration(int32_t &code)135     void FfiVibratorStopVibration(int32_t &code)
136     {
137         code = Cancel();
138     }
139 
FfiVibratorStopVibrationMode(char* vibMode, int32_t &code)140     void FfiVibratorStopVibrationMode(char* vibMode, int32_t &code)
141     {
142         if (vibMode == nullptr) {
143             code = PARAMETER_ERROR;
144             return;
145         }
146         if (strcmp(vibMode, "time") != 0 && strcmp(vibMode, "preset") != 0) {
147             code = PARAMETER_ERROR;
148             return;
149         }
150         std::string mode(vibMode);
151         code = StopVibrator(mode.c_str());
152     }
153 
FfiVibratorSupportEffect(char* id, int32_t &code)154     bool FfiVibratorSupportEffect(char* id, int32_t &code)
155     {
156         bool isSupportEffect = false;
157         if (id == nullptr) {
158             code = PARAMETER_ERROR;
159             return isSupportEffect;
160         }
161         if (strcmp(id, "haptic.clock.timer") != 0) {
162             code = PARAMETER_ERROR;
163             return isSupportEffect;
164         }
165         std::string effectId(id);
166         code = IsSupportEffect(effectId.c_str(), &isSupportEffect);
167         return isSupportEffect;
168     }
169 
FfiVibratorIsHdHapticSupported()170     bool FfiVibratorIsHdHapticSupported()
171     {
172         return IsHdHapticSupported();
173     }
174 }
175 }
176 }