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