• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_device_selection_listener.h"
17 
18 #include "base/continuationmgr_log.h"
19 #include "js_runtime_utils.h"
20 #include "napi_common_util.h"
21 
22 namespace OHOS {
23 namespace DistributedSchedule {
24 using namespace OHOS::AbilityRuntime;
25 namespace {
26 const std::string TAG = "JsDeviceSelectionListener";
27 }
28 
OnDeviceConnect(const std::vector<ContinuationResult> & continuationResults)29 void JsDeviceSelectionListener::OnDeviceConnect(const std::vector<ContinuationResult>& continuationResults)
30 {
31     HILOGD("called.");
32     CallJsMethod(EVENT_CONNECT, continuationResults);
33 }
34 
OnDeviceDisconnect(const std::vector<ContinuationResult> & continuationResults)35 void JsDeviceSelectionListener::OnDeviceDisconnect(const std::vector<ContinuationResult>& continuationResults)
36 {
37     HILOGD("called.");
38     CallJsMethod(EVENT_DISCONNECT, continuationResults);
39 }
40 
AddCallback(const std::string & cbType,NativeValue * jsListenerObj)41 void JsDeviceSelectionListener::AddCallback(const std::string& cbType, NativeValue* jsListenerObj)
42 {
43     HILOGD("called.");
44     std::unique_ptr<NativeReference> callbackRef;
45     if (engine_ == nullptr) {
46         HILOGE("engine_ is nullptr");
47         return;
48     }
49     callbackRef.reset(engine_->CreateReference(jsListenerObj, 1));
50 
51     std::lock_guard<std::mutex> jsCallBackMapLock(jsCallBackMapMutex_);
52     jsCallBackMap_[cbType] = std::move(callbackRef);
53     HILOGD("jsCallBackMap_ cbType: %{public}s, size: %{public}u!",
54         cbType.c_str(), static_cast<uint32_t>(jsCallBackMap_.size()));
55 }
56 
RemoveCallback(const std::string & cbType)57 void JsDeviceSelectionListener::RemoveCallback(const std::string& cbType)
58 {
59     HILOGD("called.");
60     std::lock_guard<std::mutex> jsCallBackMapLock(jsCallBackMapMutex_);
61     jsCallBackMap_.erase(cbType);
62     HILOGD("jsCallBackMap_ cbType: %{public}s, size: %{public}u!",
63         cbType.c_str(), static_cast<uint32_t>(jsCallBackMap_.size()));
64 }
65 
CallJsMethod(const std::string & methodName,const std::vector<ContinuationResult> & continuationResults)66 void JsDeviceSelectionListener::CallJsMethod(const std::string& methodName,
67     const std::vector<ContinuationResult>& continuationResults)
68 {
69     HILOGD("methodName = %{public}s", methodName.c_str());
70     if (engine_ == nullptr) {
71         HILOGE("engine_ is nullptr");
72         return;
73     }
74     // js callback should run in js thread
75     std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback>
76         ([this, methodName, continuationResults]
77             (NativeEngine &engine, AsyncTask &task, int32_t status) {
78             napi_handle_scope scope = nullptr;
79             napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
80             if (scope == nullptr) {
81                 return;
82             }
83 
84             CallJsMethodInner(methodName, continuationResults);
85 
86             napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
87         });
88     NativeReference* callback = nullptr;
89     std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
90     AsyncTask::Schedule("JsDeviceSelectionListener::OnDeviceConnect",
91         *engine_, std::make_unique<AsyncTask>(callback, std::move(execute), std::move(complete)));
92 }
93 
CallJsMethodInner(const std::string & methodName,const std::vector<ContinuationResult> & continuationResults)94 void JsDeviceSelectionListener::CallJsMethodInner(const std::string& methodName,
95     const std::vector<ContinuationResult>& continuationResults)
96 {
97     std::lock_guard<std::mutex> jsCallBackMapLock(jsCallBackMapMutex_);
98     NativeValue* method = jsCallBackMap_[methodName]->Get();
99     if (method == nullptr) {
100         HILOGE("Failed to get %{public}s from object", methodName.c_str());
101         return;
102     }
103     NativeValue* argv[] = { WrapContinuationResultArray(*engine_, continuationResults) };
104     engine_->CallFunction(engine_->CreateUndefined(), method, argv, ArraySize(argv));
105 }
106 
CallJsMethod(const std::string & methodName,const std::vector<std::string> & deviceIds)107 void JsDeviceSelectionListener::CallJsMethod(const std::string& methodName, const std::vector<std::string>& deviceIds)
108 {
109     HILOGD("methodName = %{public}s", methodName.c_str());
110     if (engine_ == nullptr) {
111         HILOGE("engine_ is nullptr");
112         return;
113     }
114     // js callback should run in js thread
115     std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback>
116         ([this, methodName, deviceIds]
117             (NativeEngine &engine, AsyncTask &task, int32_t status) {
118             napi_handle_scope scope = nullptr;
119             napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
120             if (scope == nullptr) {
121                 return;
122             }
123 
124             CallJsMethodInner(methodName, deviceIds);
125 
126             napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
127         });
128     NativeReference* callback = nullptr;
129     std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
130     AsyncTask::Schedule("JsDeviceSelectionListener::OnDeviceDisconnect",
131         *engine_, std::make_unique<AsyncTask>(callback, std::move(execute), std::move(complete)));
132 }
133 
CallJsMethodInner(const std::string & methodName,const std::vector<std::string> & deviceIds)134 void JsDeviceSelectionListener::CallJsMethodInner(const std::string& methodName,
135     const std::vector<std::string>& deviceIds)
136 {
137     std::lock_guard<std::mutex> jsCallBackMapLock(jsCallBackMapMutex_);
138     NativeValue* method = jsCallBackMap_[methodName]->Get();
139     if (method == nullptr) {
140         HILOGE("Failed to get %{public}s from object", methodName.c_str());
141         return;
142     }
143     NativeValue* argv[] = { WrapDeviceIdArray(*engine_, deviceIds) };
144     engine_->CallFunction(engine_->CreateUndefined(), method, argv, ArraySize(argv));
145 }
146 
WrapContinuationResult(NativeEngine & engine,const ContinuationResult & continuationResult)147 NativeValue* JsDeviceSelectionListener::WrapContinuationResult(NativeEngine& engine,
148     const ContinuationResult& continuationResult)
149 {
150     NativeValue* objValue = engine.CreateObject();
151     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
152     object->SetProperty("id", CreateJsValue(engine, continuationResult.GetDeviceId()));
153     object->SetProperty("type", CreateJsValue(engine, continuationResult.GetDeviceType()));
154     object->SetProperty("name", CreateJsValue(engine, continuationResult.GetDeviceName()));
155     return objValue;
156 }
157 
WrapContinuationResultArray(NativeEngine & engine,const std::vector<ContinuationResult> & continuationResults)158 NativeValue* JsDeviceSelectionListener::WrapContinuationResultArray(NativeEngine& engine,
159     const std::vector<ContinuationResult>& continuationResults)
160 {
161     NativeValue* arrayValue = engine.CreateArray(continuationResults.size());
162     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
163     uint32_t index = 0;
164     for (const auto& continuationResult : continuationResults) {
165         array->SetElement(index++, WrapContinuationResult(engine, continuationResult));
166     }
167     return arrayValue;
168 }
169 
WrapDeviceIdArray(NativeEngine & engine,const std::vector<std::string> & deviceIds)170 NativeValue* JsDeviceSelectionListener::WrapDeviceIdArray(NativeEngine& engine,
171     const std::vector<std::string>& deviceIds)
172 {
173     NativeValue* arrayValue = engine.CreateArray(deviceIds.size());
174     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
175     uint32_t index = 0;
176     for (const auto& deviceId : deviceIds) {
177         array->SetElement(index++, CreateJsValue(engine, deviceId));
178     }
179     return arrayValue;
180 }
181 }  // namespace DistributedSchedule
182 }  // namespace OHOS