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 "js_register_module.h"
17 #include <linux/input.h>
18
19 #include "input_manager.h"
20 #include "mmi_log.h"
21 #include "napi_constants.h"
22 #include "util_napi_error.h"
23 #include "util_napi.h"
24
25 #undef MMI_LOG_TAG
26 #define MMI_LOG_TAG "JsInfraredRegister"
27
28 namespace OHOS {
29 namespace MMI {
30 namespace {
31 const uint32_t NUMBER_PARAMETERS { 2 };
32 constexpr int32_t MAX_NUMBER_ARRAY_ELEMENT { 1024 };
33 }
34
CheckType(const napi_env & env,const napi_value & value,const napi_valuetype & type)35 bool CheckType(const napi_env& env, const napi_value& value, const napi_valuetype& type)
36 {
37 napi_valuetype valuetype = napi_undefined;
38 napi_typeof(env, value, &valuetype);
39 if (valuetype != type) {
40 return false;
41 }
42 return true;
43 }
44
IsArray(const napi_env & env,const napi_value & value)45 bool IsArray(const napi_env& env, const napi_value& value)
46 {
47 bool isArray = false;
48 if (napi_is_array(env, value, &isArray) != napi_ok) {
49 MMI_HILOGE("napi_is_array failed");
50 return false;
51 }
52 return isArray;
53 }
54
ParseInt64(const napi_env & env,const napi_value & value,int64_t & result)55 bool ParseInt64(const napi_env& env, const napi_value& value, int64_t& result)
56 {
57 if (!CheckType(env, value, napi_number)) {
58 MMI_HILOGE("ParseInt64 type not number");
59 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element of pattern", "Number");
60 return false;
61 }
62 if (napi_get_value_int64(env, value, &result) != napi_ok) {
63 MMI_HILOGE("ParseInt64 cannot get value int64");
64 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element of pattern", "Int64");
65 return false;
66 }
67 return true;
68 }
69
ParsePatternArray(const napi_env & env,const napi_value & value,std::vector<int64_t> & result)70 bool ParsePatternArray(const napi_env& env, const napi_value& value, std::vector<int64_t>& result)
71 {
72 uint32_t length = 0;
73 if (!IsArray(env, value)) {
74 MMI_HILOGE("ParsePatternArray second para not array");
75 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "pattern", "Array");
76 return false;
77 }
78 napi_get_array_length(env, value, &length);
79 for (uint32_t i = 0; i < length; i++) {
80 napi_value valueArray = nullptr;
81 if (napi_get_element(env, value, i, &valueArray) != napi_ok) {
82 MMI_HILOGE("ParsePatternArray napi_get_element failed. index:%{public}d", i);
83 return false;
84 }
85 int64_t res = 0;
86 if (!ParseInt64(env, valueArray, res)) {
87 MMI_HILOGE("ParsePatternArray parse array fail. index:%{public}d", i);
88 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element of pattern", "Int64");
89 return false;
90 }
91 if (res <= 0) {
92 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "value for element of pattern", "must be positive");
93 return false;
94 }
95 result.emplace_back(res);
96 }
97 return true;
98 };
99
ParseTransmitInfraredJSParam(const napi_env & env,const napi_callback_info & info,int64_t & infraredFrequency,std::vector<int64_t> & vecPattern)100 bool ParseTransmitInfraredJSParam(const napi_env& env, const napi_callback_info &info, int64_t & infraredFrequency,
101 std::vector<int64_t> & vecPattern)
102 {
103 CALL_DEBUG_ENTER;
104 size_t argc = NUMBER_PARAMETERS;
105 napi_value argv[NUMBER_PARAMETERS] = { 0 };
106 CHKRF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
107 if (argc != NUMBER_PARAMETERS) {
108 MMI_HILOGE("ParseTransmitInfraredJSParam Parameter number error");
109 return false;
110 }
111 if (!CheckType(env, argv[0], napi_number)) {
112 MMI_HILOGE("ParseTransmitInfraredJSParam infraredFrequency parameter[0] type is invalid");
113 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "infraredFrequency", "number");
114 return false;
115 }
116 CHKRF(napi_get_value_int64(env, argv[0], &infraredFrequency), "get number64 value error");
117 if (infraredFrequency <= 0) {
118 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "value of infraredFrequency", "must be greater than 0");
119 return false;
120 }
121 if (!ParsePatternArray(env, argv[1], vecPattern)) {
122 MMI_HILOGE("ParsePatternArray parse pattern array fail");
123 return false;
124 }
125 if (vecPattern.size() > MAX_NUMBER_ARRAY_ELEMENT) {
126 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "size of pattern", "must be less than or equal 50");
127 return false;
128 }
129 return true;
130 }
131
ThrowError(napi_env env,int32_t code,std::string operateType)132 static void ThrowError(napi_env env, int32_t code, std::string operateType)
133 {
134 int32_t errorCode = -code;
135 if (code > 0) {
136 errorCode = code;
137 }
138 MMI_HILOGE("Operate %{public}s requst error. returnCode:%{public}d", operateType.c_str(), code);
139 if (errorCode == COMMON_PERMISSION_CHECK_ERROR) {
140 THROWERR_API9(env, COMMON_PERMISSION_CHECK_ERROR, "Infrared", "ohos.permission.MANAGE_INPUT_INFRARED_EMITTER");
141 } else if (COMMON_USE_SYSAPI_ERROR == errorCode) {
142 THROWERR_API9(env, COMMON_USE_SYSAPI_ERROR, "Infrared", "Non system applications use system API");
143 } else {
144 return;
145 }
146 }
147
CreateInfraredFrequencyItem(napi_env env,const InfraredFrequency & infraredFrequency)148 napi_value CreateInfraredFrequencyItem(napi_env env, const InfraredFrequency &infraredFrequency)
149 {
150 napi_value result;
151 napi_status status = napi_create_object(env, &result);
152 CHKRP(status, CREATE_OBJECT);
153 napi_value jsMax;
154 CHKRP(napi_create_int64(env, infraredFrequency.max_, &jsMax), "napi_create_int64:max");
155 CHKRP(napi_set_named_property(env, result, "max", jsMax), SET_NAMED_PROPERTY);
156 napi_value jsMin;
157 CHKRP(napi_create_int64(env, infraredFrequency.min_, &jsMin), "napi_create_int64:min");
158 CHKRP(napi_set_named_property(env, result, "min", jsMin), SET_NAMED_PROPERTY);
159 return result;
160 }
161
HasIrEmitter(napi_env env,napi_callback_info info)162 static napi_value HasIrEmitter(napi_env env, napi_callback_info info)
163 {
164 CALL_DEBUG_ENTER;
165 napi_value result = nullptr;
166 napi_status status = napi_get_boolean(env, true, &result);
167 if (status != napi_ok) {
168 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "boolean");
169 return nullptr;
170 }
171 return result;
172 }
173
GetInfraredFrequencies(napi_env env,napi_callback_info info)174 static napi_value GetInfraredFrequencies(napi_env env, napi_callback_info info)
175 {
176 CALL_DEBUG_ENTER;
177 napi_value result = nullptr;
178 CHKRP(napi_create_array(env, &result), CREATE_ARRAY);
179 std::vector<InfraredFrequency> requencys;
180 int32_t ret = InputManager::GetInstance()->GetInfraredFrequencies(requencys);
181 if (ret != RET_OK) {
182 if (RET_OK > ret || COMMON_PERMISSION_CHECK_ERROR == ret || ERROR_NOT_SYSAPI == ret) {
183 MMI_HILOGE("js_register.GetFreq reqErr. Permi Err or Not System APP. Positive retCode:%{public}d", ret);
184 ThrowError(env, ret, "GetInfraredFrequencies");
185 }
186 MMI_HILOGE("Parse GetInfraredFrequencies requst error. returnCode:%{public}d", ret);
187 return result;
188 }
189 size_t size = requencys.size();
190 std::string logPrint = "size:" + std::to_string(size) + ";";
191 CHKRP(napi_create_array(env, &result), CREATE_ARRAY);
192 for (size_t i = 0; i < size; i++) {
193 InfraredFrequency frequencyItem = requencys[i];
194 logPrint = logPrint + std::to_string(i) + "max:" + std::to_string(frequencyItem.max_) + ";min:"
195 + std::to_string(frequencyItem.min_) + ";";
196 napi_value item = CreateInfraredFrequencyItem(env, requencys[i]);
197 if (item == nullptr) {
198 MMI_HILOGE("CreateInfraredFrequencyItem error");
199 return nullptr;
200 }
201 CHKRP(napi_set_element(env, result, i, item), SET_ELEMENT);
202 }
203 MMI_HILOGD("js_register_module.GetInfraredFrequencies:%{public}s ", logPrint.c_str());
204 return result;
205 }
206
TransmitInfrared(napi_env env,napi_callback_info info)207 static napi_value TransmitInfrared(napi_env env, napi_callback_info info)
208 {
209 CALL_DEBUG_ENTER;
210 napi_value result = nullptr;
211 int64_t number = -1;
212 std::vector<int64_t> pattern;
213 if (!ParseTransmitInfraredJSParam(env, info, number, pattern)) {
214 MMI_HILOGE("Parse TransmitInfrared JSParam error");
215 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parse TransmitInfrared JSParam error");
216 return nullptr;
217 }
218 int32_t size = static_cast<int32_t>(pattern.size());
219 std::string context = "number:" + std::to_string(number) + "\n;" + "; size=" + std::to_string(size) + ";";
220 for (int32_t i = 0; i < size; i++) {
221 context = context + std::to_string(i) + ": pattern: " + std::to_string(pattern[i]) + ";";
222 }
223 MMI_HILOGD("js_register_module.TransmitInfrared para size:%{public}s", context.c_str());
224 int32_t ret = InputManager::GetInstance()->TransmitInfrared(number, pattern);
225 if (ret != RET_OK) {
226 if (RET_OK > ret || COMMON_PERMISSION_CHECK_ERROR == ret || ERROR_NOT_SYSAPI == ret) {
227 MMI_HILOGE("js_register.Transmit req err. Per Er or Not Sys APP. Posi retCode:%{public}d", ret);
228 ThrowError(env, ret, "TransmitInfrared");
229 }
230 MMI_HILOGE("js_register_module.TransmitInfrared requst error. returnCode:%{public}d", ret);
231 return nullptr;
232 }
233 CHKRP(napi_create_int32(env, 0, &result), CREATE_INT32);
234 return result;
235 }
236
237 EXTERN_C_START
MmiInit(napi_env env,napi_value exports)238 static napi_value MmiInit(napi_env env, napi_value exports)
239 {
240 CALL_DEBUG_ENTER;
241 napi_property_descriptor desc[] = {
242 DECLARE_NAPI_FUNCTION("hasIrEmitter", HasIrEmitter),
243 DECLARE_NAPI_FUNCTION("getInfraredFrequencies", GetInfraredFrequencies),
244 DECLARE_NAPI_FUNCTION("transmitInfrared", TransmitInfrared)
245 };
246 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
247 return exports;
248 }
249 EXTERN_C_END
250
251 static napi_module infraredModule = {
252 .nm_version = 1,
253 .nm_flags = 0,
254 .nm_filename = nullptr,
255 .nm_register_func = MmiInit,
256 .nm_modname = "multimodalInput.infraredEmitter",
257 .nm_priv = ((void*)0),
258 .reserved = { 0 },
259 };
260
RegisterModule(void)261 extern "C" __attribute__((constructor)) void RegisterModule(void)
262 {
263 napi_module_register(&infraredModule);
264 }
265
266 }
267 }