• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "native_distributedhardwarefwk_js.h"
17 
18 #include "ipc_skeleton.h"
19 #include "js_native_api.h"
20 #include "tokenid_kit.h"
21 
22 #include "device_type.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 &paramName, 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 
CreateBusinessErr(napi_env env,int32_t errCode)123 napi_value DistributedHardwareManager::CreateBusinessErr(napi_env env, int32_t errCode)
124 {
125     napi_value error = nullptr;
126     switch (static_cast<DHBussinessErrorCode>(errCode)) {
127         case ERR_NOT_SYSTEM_APP:
128             napi_throw_error(env, std::to_string(errCode).c_str(), ERR_MESSAGE_NOT_SYSTEM_APP.c_str());
129             break;
130         case ERR_NO_PERMISSION:
131             napi_throw_error(env, std::to_string(errCode).c_str(), ERR_MESSAGE_NO_PERMISSION.c_str());
132             break;
133         case ERR_INVALID_PARAMS:
134             napi_throw_error(env, std::to_string(errCode).c_str(), ERR_MESSAGE_INVALID_PARAMS.c_str());
135             break;
136         default:
137             break;
138     }
139     return error;
140 }
141 
PauseDistributedHardware(napi_env env,napi_callback_info info)142 napi_value DistributedHardwareManager::PauseDistributedHardware(napi_env env, napi_callback_info info)
143 {
144     DHLOGI("PauseDistributedHardware in");
145     if (!IsSystemApp()) {
146         CreateBusinessErr(env, ERR_NOT_SYSTEM_APP);
147         return nullptr;
148     }
149     napi_value result = nullptr;
150     size_t argc = 2;
151     napi_value argv[2] = {nullptr};
152     napi_value thisVar = nullptr;
153     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
154     NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
155 
156     napi_valuetype valueType = napi_undefined;
157     napi_typeof(env, argv[0], &valueType);
158     if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
159         return nullptr;
160     }
161     int32_t type = -1;
162     char networkId[96];
163     JsObjectToInt(env, argv[0], "type", type);
164     DHType dhType = DHType::UNKNOWN;
165     DHSubtype dhSubtype = static_cast<DHSubtype>(type);
166     if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
167         dhType = DHType::AUDIO;
168     } else if (dhSubtype == DHSubtype::CAMERA) {
169         dhType = DHType::CAMERA;
170     }
171     JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
172     std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
173     if (argc == DH_NAPI_ARGS_ONE) {    // promise
174         napi_deferred deferred;
175         napi_value promise = 0;
176         napi_create_promise(env, &deferred, &promise);
177         int32_t ret = dhFwkKit->PauseDistributedHardware(dhType, std::string(networkId));
178         if (ret != 0) {
179             DHLOGE("PauseDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
180         }
181         return promise;
182     } else if (argc == DH_NAPI_ARGS_TWO) {    // callback
183         if (!IsFunctionType(env, argv[1])) {
184             return nullptr;
185         }
186         int32_t ret = dhFwkKit->PauseDistributedHardware(dhType, std::string(networkId));
187         if (ret != 0) {
188             DHLOGE("PauseDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
189         }
190     }
191     napi_get_undefined(env, &result);
192     return result;
193 }
194 
ResumeDistributedHardware(napi_env env,napi_callback_info info)195 napi_value DistributedHardwareManager::ResumeDistributedHardware(napi_env env, napi_callback_info info)
196 {
197     DHLOGI("ResumeDistributedHardware in");
198     if (!IsSystemApp()) {
199         CreateBusinessErr(env, ERR_NOT_SYSTEM_APP);
200         return nullptr;
201     }
202     napi_value result = nullptr;
203     size_t argc = 2;
204     napi_value argv[2] = {nullptr};
205     napi_value thisVar = nullptr;
206     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
207     NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
208 
209     napi_valuetype valueType = napi_undefined;
210     napi_typeof(env, argv[0], &valueType);
211     if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
212         return nullptr;
213     }
214     int32_t type = -1;
215     char networkId[96];
216     JsObjectToInt(env, argv[0], "type", type);
217     DHType dhType = DHType::UNKNOWN;
218     DHSubtype dhSubtype = static_cast<DHSubtype>(type);
219     if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
220         dhType = DHType::AUDIO;
221     } else if (dhSubtype == DHSubtype::CAMERA) {
222         dhType = DHType::CAMERA;
223     }
224     JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
225     std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
226     if (argc == DH_NAPI_ARGS_ONE) {    // promise
227         napi_deferred deferred;
228         napi_value promise = 0;
229         napi_create_promise(env, &deferred, &promise);
230         int32_t ret = dhFwkKit->ResumeDistributedHardware(dhType, std::string(networkId));
231         if (ret != 0) {
232             DHLOGE("ResumeDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
233         }
234         return promise;
235     } else if (argc == DH_NAPI_ARGS_TWO) {    // callback
236         if (!IsFunctionType(env, argv[1])) {
237             return nullptr;
238         }
239         int32_t ret = dhFwkKit->ResumeDistributedHardware(dhType, std::string(networkId));
240         if (ret != 0) {
241             DHLOGE("ResumeDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
242         }
243     }
244     napi_get_undefined(env, &result);
245     return result;
246 }
247 
StopDistributedHardware(napi_env env,napi_callback_info info)248 napi_value DistributedHardwareManager::StopDistributedHardware(napi_env env, napi_callback_info info)
249 {
250     DHLOGI("StopDistributedHardware in");
251     if (!IsSystemApp()) {
252         CreateBusinessErr(env, ERR_NOT_SYSTEM_APP);
253         return nullptr;
254     }
255     napi_value result = nullptr;
256     size_t argc = 2;
257     napi_value argv[2] = {nullptr};
258     napi_value thisVar = nullptr;
259     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
260     NAPI_ASSERT(env, ((argc >= DH_NAPI_ARGS_ONE) && (argc <= DH_NAPI_ARGS_TWO)), "requires 1 or 2 parameter");
261 
262     napi_valuetype valueType = napi_undefined;
263     napi_typeof(env, argv[0], &valueType);
264     if (!CheckArgsType(env, valueType == napi_object, "description", "object")) {
265         return nullptr;
266     }
267     int32_t type = -1;
268     char networkId[96];
269     JsObjectToInt(env, argv[0], "type", type);
270     DHType dhType = DHType::UNKNOWN;
271     DHSubtype dhSubtype = static_cast<DHSubtype>(type);
272     if (dhSubtype == DHSubtype::AUDIO_MIC || dhSubtype == DHSubtype::AUDIO_SPEAKER) {
273         dhType = DHType::AUDIO;
274     } else if (dhSubtype == DHSubtype::CAMERA) {
275         dhType = DHType::CAMERA;
276     }
277     JsObjectToString(env, argv[0], "srcNetworkId", networkId, sizeof(networkId));
278     std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = std::make_shared<DistributedHardwareFwkKit>();
279     if (argc == DH_NAPI_ARGS_ONE) {    // promise
280         napi_deferred deferred;
281         napi_value promise = 0;
282         napi_create_promise(env, &deferred, &promise);
283         int32_t ret = dhFwkKit->StopDistributedHardware(dhType, std::string(networkId));
284         if (ret != 0) {
285             DHLOGE("StopDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
286         }
287         return promise;
288     } else if (argc == DH_NAPI_ARGS_TWO) {    // callback
289         if (!IsFunctionType(env, argv[1])) {
290             return nullptr;
291         }
292         int32_t ret = dhFwkKit->StopDistributedHardware(dhType, std::string(networkId));
293         if (ret != 0) {
294             DHLOGE("StopDistributedHardware for DHType: %{public}u filed", (uint32_t)dhType);
295         }
296     }
297     napi_get_undefined(env, &result);
298     return result;
299 }
300 
Init(napi_env env,napi_value exports)301 napi_value DistributedHardwareManager::Init(napi_env env, napi_value exports)
302 {
303     napi_property_descriptor dhmProperties[] = {
304         DECLARE_NAPI_FUNCTION("pauseDistributedHardware", PauseDistributedHardware),
305         DECLARE_NAPI_FUNCTION("resumeDistributedHardware", ResumeDistributedHardware),
306         DECLARE_NAPI_FUNCTION("stopDistributedHardware", StopDistributedHardware),
307     };
308 
309     DHLOGI("DistributedHardwareManager::Init is called!");
310     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(dhmProperties) / sizeof(dhmProperties[0]),
311         dhmProperties));
312     DHLOGI("All functions are configured..");
313     return exports;
314 }
315 
InitDistributedHardwareType(napi_env env,napi_value exports)316 void DistributedHardwareManager::InitDistributedHardwareType(napi_env env, napi_value exports)
317 {
318     char propertyName[] = "DistributedHardwareType";
319     napi_value all = nullptr;
320     napi_value camera = nullptr;
321     napi_value screen = nullptr;
322     napi_value modemMic = nullptr;
323     napi_value modemSpk = nullptr;
324     napi_value mic = nullptr;
325     napi_value speaker = nullptr;
326     napi_create_int32(env, ALL, &all);
327     napi_create_int32(env, CAMERA, &camera);
328     napi_create_int32(env, SCREEN, &screen);
329     napi_create_int32(env, MODEM_MIC, &modemMic);
330     napi_create_int32(env, MODEM_SPEAKER, &modemSpk);
331     napi_create_int32(env, MIC, &mic);
332     napi_create_int32(env, SPEAKER, &speaker);
333     napi_property_descriptor desc[] = {
334         DECLARE_NAPI_STATIC_PROPERTY("ALL", all),
335         DECLARE_NAPI_STATIC_PROPERTY("CAMERA", camera),
336         DECLARE_NAPI_STATIC_PROPERTY("SCREEN", screen),
337         DECLARE_NAPI_STATIC_PROPERTY("MODEM_MIC", modemMic),
338         DECLARE_NAPI_STATIC_PROPERTY("MODEM_SPEAKER", modemSpk),
339         DECLARE_NAPI_STATIC_PROPERTY("MIC", mic),
340         DECLARE_NAPI_STATIC_PROPERTY("SPEAKER", speaker)
341     };
342     napi_value obj = nullptr;
343     napi_create_object(env, &obj);
344     napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
345     napi_set_named_property(env, exports, propertyName, obj);
346 }
347 
348 /*
349  * Function registering all props and functions of ohos.distributedhardware
350  */
Export(napi_env env,napi_value exports)351 static napi_value Export(napi_env env, napi_value exports)
352 {
353     DHLOGI("Export is called!");
354     DistributedHardwareManager::Init(env, exports);
355     DistributedHardwareManager::InitDistributedHardwareType(env, exports);
356     return exports;
357 }
358 
359 /*
360  * module define
361  */
362 static napi_module g_dhModule = {.nm_version = 1,
363                                  .nm_flags = 0,
364                                  .nm_filename = nullptr,
365                                  .nm_register_func = Export,
366                                  .nm_modname = "distributedHardware.hardwareManager",
367                                  .nm_priv = ((void *)0),
368                                  .reserved = {0}};
369 
370 /*
371  * module register
372  */
RegisterModule(void)373 extern "C" __attribute__((constructor)) void RegisterModule(void)
374 {
375     DHLOGI("RegisterModule is called!");
376     napi_module_register(&g_dhModule);
377 }