1 /*
2 * Copyright (c) 2023-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 "native_distributedhardwarefwk_js.h"
17
18 #include "device_type.h"
19 #include "ipc_skeleton.h"
20 #include "js_native_api.h"
21 #include "tokenid_kit.h"
22 #include "cJSON.h"
23 #include "distributed_hardware_log.h"
24 #include "distributed_hardware_fwk_kit.h"
25
26 using namespace OHOS::DistributedHardware;
27
28 namespace {
29 #define GET_PARAMS(env, info, num) \
30 size_t argc = num; \
31 napi_value argv[num] = {nullptr}; \
32 napi_value thisVar = nullptr; \
33 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr))
34
35 const int32_t DH_NAPI_ARGS_ONE = 1;
36 const int32_t DH_NAPI_ARGS_TWO = 2;
37
38 enum DHBussinessErrorCode {
39 // Permission verify failed.
40 ERR_NO_PERMISSION = 201,
41 // The caller is not a system application.
42 ERR_NOT_SYSTEM_APP = 202,
43 // Input parameter error.
44 ERR_INVALID_PARAMS = 401,
45 // The distributed hardware is not started.
46 ERR_CODE_DH_NOT_START = 24200101,
47 // The source device is not connected.
48 ERR_CODE_DEVICE_NOT_CONNECT = 24200102,
49 };
50
51 const std::string ERR_MESSAGE_INVALID_PARAMS = "Input parameter error.";
52 const std::string ERR_MESSAGE_NO_PERMISSION = "Permission verify failed.";
53 const std::string ERR_MESSAGE_NOT_SYSTEM_APP = "The caller is not a system application.";
54 const std::string ERR_MESSAGE_DH_NOT_START = "The distributed hardware is not started.";
55 const std::string ERR_MESSAGE_DEVICE_NOT_CONNECT = "The source device is not connected.";
56
CheckArgsType(napi_env env,bool assertion,const std::string & paramName,const std::string & type)57 bool CheckArgsType(napi_env env, bool assertion, const std::string ¶mName, const std::string &type)
58 {
59 if (!(assertion)) {
60 std::string errMsg = ERR_MESSAGE_INVALID_PARAMS + "The type of " + paramName +
61 " must be " + type;
62 napi_throw_error(env, std::to_string(ERR_INVALID_PARAMS).c_str(), errMsg.c_str());
63 return false;
64 }
65 return true;
66 }
67
IsFunctionType(napi_env env,napi_value value)68 bool IsFunctionType(napi_env env, napi_value value)
69 {
70 napi_valuetype eventHandleType = napi_undefined;
71 napi_typeof(env, value, &eventHandleType);
72 return CheckArgsType(env, eventHandleType == napi_function, "callback", "function");
73 }
74 } // namespace
75
JsObjectToString(const napi_env & env,const napi_value & object,const std::string & fieldStr,char * dest,const int32_t destLen)76 void DistributedHardwareManager::JsObjectToString(const napi_env &env, const napi_value &object,
77 const std::string &fieldStr, char *dest, const int32_t destLen)
78 {
79 bool hasProperty = false;
80 NAPI_CALL_RETURN_VOID(env, napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty));
81 if (hasProperty) {
82 napi_value field = nullptr;
83 napi_valuetype valueType = napi_undefined;
84
85 napi_get_named_property(env, object, fieldStr.c_str(), &field);
86 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, field, &valueType));
87 if (!CheckArgsType(env, valueType == napi_string, fieldStr.c_str(), "string")) {
88 return;
89 }
90 size_t result = 0;
91 NAPI_CALL_RETURN_VOID(env, napi_get_value_string_utf8(env, field, dest, destLen, &result));
92 } else {
93 DHLOGE("devicemanager napi js to str no property: %{public}s", fieldStr.c_str());
94 }
95 }
96
JsObjectToInt(const napi_env & env,const napi_value & object,const std::string & fieldStr,int32_t & fieldRef)97 void DistributedHardwareManager::JsObjectToInt(const napi_env &env, const napi_value &object,
98 const std::string &fieldStr, int32_t &fieldRef)
99 {
100 bool hasProperty = false;
101 NAPI_CALL_RETURN_VOID(env, napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty));
102 if (hasProperty) {
103 napi_value field = nullptr;
104 napi_valuetype valueType = napi_undefined;
105
106 napi_get_named_property(env, object, fieldStr.c_str(), &field);
107 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, field, &valueType));
108 if (!CheckArgsType(env, valueType == napi_number, fieldStr.c_str(), "number")) {
109 return;
110 }
111 napi_get_value_int32(env, field, &fieldRef);
112 } else {
113 DHLOGE("devicemanager napi js to int no property: %{public}s", fieldStr.c_str());
114 }
115 }
116
IsSystemApp()117 bool DistributedHardwareManager::IsSystemApp()
118 {
119 uint64_t tokenId = OHOS::IPCSkeleton::GetSelfTokenID();
120 return OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
121 }
122
PauseDistributedHardware(napi_env env,napi_callback_info info)123 napi_value DistributedHardwareManager::PauseDistributedHardware(napi_env env, napi_callback_info info)
124 {
125 DHLOGI("PauseDistributedHardware in");
126 if (!IsSystemApp()) {
127 return nullptr;
128 }
129 napi_value result = nullptr;
130 size_t argc = 2;
131 napi_value argv[2] = {nullptr};
132 napi_value thisVar = nullptr;
133 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
134 NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
135
136 napi_valuetype valueType = napi_undefined;
137 napi_typeof(env, argv[0], &valueType);
138 if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
139 return nullptr;
140 }
141 int32_t type = -1;
142 char networkId[96];
143 JsObjectToInt(env, argv[0], "type", type);
144 DHType dhType = DHType::UNKNOWN;
145 DHSubtype dhSubtype = static_cast<DHSubtype>(type);
146 if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
147 dhType = DHType::AUDIO;
148 } else if (dhSubtype == DHSubtype::CAMERA) {
149 dhType = DHType::CAMERA;
150 }
151 JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
152 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
153 if (argc == DH_NAPI_ARGS_ONE) { // promise
154 napi_deferred deferred;
155 napi_value promise = 0;
156 napi_create_promise(env, &deferred, &promise);
157 int32_t ret = dhFwkKit->PauseDistributedHardware(dhType, std::string(networkId));
158 if (ret != 0) {
159 DHLOGE("PauseDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
160 }
161 return promise;
162 } else if (argc == DH_NAPI_ARGS_TWO) { // callback
163 if (!IsFunctionType(env, argv[1])) {
164 return nullptr;
165 }
166 int32_t ret = dhFwkKit->PauseDistributedHardware(dhType, std::string(networkId));
167 if (ret != 0) {
168 DHLOGE("PauseDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
169 }
170 }
171 napi_get_undefined(env, &result);
172 return result;
173 }
174
ResumeDistributedHardware(napi_env env,napi_callback_info info)175 napi_value DistributedHardwareManager::ResumeDistributedHardware(napi_env env, napi_callback_info info)
176 {
177 DHLOGI("ResumeDistributedHardware in");
178 if (!IsSystemApp()) {
179 return nullptr;
180 }
181 napi_value result = nullptr;
182 size_t argc = 2;
183 napi_value argv[2] = {nullptr};
184 napi_value thisVar = nullptr;
185 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
186 NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
187
188 napi_valuetype valueType = napi_undefined;
189 napi_typeof(env, argv[0], &valueType);
190 if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
191 return nullptr;
192 }
193 int32_t type = -1;
194 char networkId[96];
195 JsObjectToInt(env, argv[0], "type", type);
196 DHType dhType = DHType::UNKNOWN;
197 DHSubtype dhSubtype = static_cast<DHSubtype>(type);
198 if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
199 dhType = DHType::AUDIO;
200 } else if (dhSubtype == DHSubtype::CAMERA) {
201 dhType = DHType::CAMERA;
202 }
203 JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
204 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
205 if (argc == DH_NAPI_ARGS_ONE) { // promise
206 napi_deferred deferred;
207 napi_value promise = 0;
208 napi_create_promise(env, &deferred, &promise);
209 int32_t ret = dhFwkKit->ResumeDistributedHardware(dhType, std::string(networkId));
210 if (ret != 0) {
211 DHLOGE("ResumeDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
212 }
213 return promise;
214 } else if (argc == DH_NAPI_ARGS_TWO) { // callback
215 if (!IsFunctionType(env, argv[1])) {
216 return nullptr;
217 }
218 int32_t ret = dhFwkKit->ResumeDistributedHardware(dhType, std::string(networkId));
219 if (ret != 0) {
220 DHLOGE("ResumeDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
221 }
222 }
223 napi_get_undefined(env, &result);
224 return result;
225 }
226
StopDistributedHardware(napi_env env,napi_callback_info info)227 napi_value DistributedHardwareManager::StopDistributedHardware(napi_env env, napi_callback_info info)
228 {
229 DHLOGI("StopDistributedHardware in");
230 if (!IsSystemApp()) {
231 return nullptr;
232 }
233 napi_value result = nullptr;
234 size_t argc = 2;
235 napi_value argv[2] = {nullptr};
236 napi_value thisVar = nullptr;
237 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
238 NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
239
240 napi_valuetype valueType = napi_undefined;
241 napi_typeof(env, argv[0], &valueType);
242 if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
243 return nullptr;
244 }
245 int32_t type = -1;
246 char networkId[96];
247 JsObjectToInt(env, argv[0], "type", type);
248 DHType dhType = DHType::UNKNOWN;
249 DHSubtype dhSubtype = static_cast<DHSubtype>(type);
250 if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
251 dhType = DHType::AUDIO;
252 } else if (dhSubtype == DHSubtype::CAMERA) {
253 dhType = DHType::CAMERA;
254 }
255 JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
256 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
257 if (argc == DH_NAPI_ARGS_ONE) { // promise
258 napi_deferred deferred;
259 napi_value promise = 0;
260 napi_create_promise(env, &deferred, &promise);
261 int32_t ret = dhFwkKit->StopDistributedHardware(dhType, std::string(networkId));
262 if (ret != 0) {
263 DHLOGE("StopDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
264 }
265 return promise;
266 } else if (argc == DH_NAPI_ARGS_TWO) { // callback
267 if (!IsFunctionType(env, argv[1])) {
268 return nullptr;
269 }
270 int32_t ret = dhFwkKit->StopDistributedHardware(dhType, std::string(networkId));
271 if (ret != 0) {
272 DHLOGE("StopDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
273 }
274 }
275 napi_get_undefined(env, &result);
276 return result;
277 }
278
Init(napi_env env,napi_value exports)279 napi_value DistributedHardwareManager::Init(napi_env env, napi_value exports)
280 {
281 napi_property_descriptor dhmProperties[] = {
282 DECLARE_NAPI_FUNCTION("pauseDistributedHardware", PauseDistributedHardware),
283 DECLARE_NAPI_FUNCTION("resumeDistributedHardware", ResumeDistributedHardware),
284 DECLARE_NAPI_FUNCTION("stopDistributedHardware", StopDistributedHardware),
285 };
286
287 DHLOGI("DistributedHardwareManager::Init is called!");
288 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(dhmProperties) / sizeof(dhmProperties[0]),
289 dhmProperties));
290 DHLOGI("All functions are configured..");
291 return exports;
292 }
293
294 /*
295 * Function registering all props and functions of ohos.distributedhardware
296 */
Export(napi_env env,napi_value exports)297 static napi_value Export(napi_env env, napi_value exports)
298 {
299 DHLOGI("Export is called!");
300 DistributedHardwareManager::Init(env, exports);
301 return exports;
302 }
303
304 /*
305 * module define
306 */
307 static napi_module g_dhModule = {.nm_version = 1,
308 .nm_flags = 0,
309 .nm_filename = nullptr,
310 .nm_register_func = Export,
311 .nm_modname = "distributedHardware.hardwareManager",
312 .nm_priv = ((void *)0),
313 .reserved = {0}};
314
315 /*
316 * module register
317 */
RegisterModule(void)318 extern "C" __attribute__((constructor)) void RegisterModule(void)
319 {
320 DHLOGI("RegisterModule is called!");
321 napi_module_register(&g_dhModule);
322 }