1 /*
2 * Copyright (c) 2022 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 #include "js_screen_listener.h"
16 #include "js_runtime_utils.h"
17 #include "window_manager_hilog.h"
18 namespace OHOS {
19 namespace Rosen {
20 using namespace AbilityRuntime;
21 namespace {
22 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsScreenListener"};
23 }
24 inline uint32_t SCREEN_DISCONNECT_TYPE = 0;
25 inline uint32_t SCREEN_CONNECT_TYPE = 1;
26
AddCallback(const std::string & type,NativeValue * jsListenerObject)27 void JsScreenListener::AddCallback(const std::string& type, NativeValue* jsListenerObject)
28 {
29 WLOGFI("JsScreenListener::AddCallback is called");
30 std::lock_guard<std::mutex> lock(mtx_);
31 std::unique_ptr<NativeReference> callbackRef;
32 callbackRef.reset(engine_->CreateReference(jsListenerObject, 1));
33 jsCallBack_[type].emplace_back(std::move(callbackRef));
34 WLOGFI("JsScreenListener::AddCallback success jsCallBack_ size: %{public}u!",
35 static_cast<uint32_t>(jsCallBack_[type].size()));
36 }
37
RemoveAllCallback()38 void JsScreenListener::RemoveAllCallback()
39 {
40 std::lock_guard<std::mutex> lock(mtx_);
41 jsCallBack_.clear();
42 }
43
RemoveCallback(const std::string & type,NativeValue * jsListenerObject)44 void JsScreenListener::RemoveCallback(const std::string& type, NativeValue* jsListenerObject)
45 {
46 std::lock_guard<std::mutex> lock(mtx_);
47 auto it = jsCallBack_.find(type);
48 if (it == jsCallBack_.end()) {
49 WLOGE("JsScreenListener::RemoveCallback no callback to remove");
50 return;
51 }
52 auto& listeners = it->second;
53 for (auto iter = listeners.begin(); iter != listeners.end();) {
54 if (jsListenerObject->StrictEquals((*iter)->Get())) {
55 listeners.erase(iter);
56 } else {
57 iter++;
58 }
59 }
60 WLOGFI("JsScreenListener::RemoveCallback success jsCallBack_ size: %{public}u!",
61 static_cast<uint32_t>(listeners.size()));
62 }
63
CallJsMethod(const std::string & methodName,NativeValue * const * argv,size_t argc)64 void JsScreenListener::CallJsMethod(const std::string& methodName, NativeValue* const* argv, size_t argc)
65 {
66 if (methodName.empty()) {
67 WLOGFE("empty method name str, call method failed");
68 return;
69 }
70 WLOGFI("CallJsMethod methodName = %{public}s", methodName.c_str());
71 if (engine_ == nullptr) {
72 WLOGFE("engine_ nullptr");
73 return;
74 }
75 for (auto& callback : jsCallBack_[methodName]) {
76 NativeValue* method = callback->Get();
77 if (method == nullptr) {
78 WLOGFE("Failed to get method callback from object");
79 continue;
80 }
81 engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc);
82 }
83 }
84
OnConnect(ScreenId id)85 void JsScreenListener::OnConnect(ScreenId id)
86 {
87 std::lock_guard<std::mutex> lock(mtx_);
88 WLOGFI("JsScreenListener::OnConnect is called");
89 if (jsCallBack_.empty()) {
90 WLOGFE("JsScreenListener::OnConnect not register!");
91 return;
92 }
93 if (jsCallBack_.find(EVENT_CONNECT) == jsCallBack_.end()) {
94 WLOGE("JsScreenListener::OnConnect not this event, return");
95 return;
96 }
97
98 std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback> (
99 [=] (NativeEngine &engine, AsyncTask &task, int32_t status) {
100 NativeValue* argv[] = {CreateJsValue(*engine_, static_cast<uint32_t>(id))};
101 CallJsMethod(EVENT_CONNECT, argv, ArraySize(argv));
102 }
103 );
104
105 NativeReference* callback = nullptr;
106 std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
107 AsyncTask::Schedule("JsScreenListener::OnConnect", *engine_, std::make_unique<AsyncTask>(
108 callback, std::move(execute), std::move(complete)));
109 }
110
OnDisconnect(ScreenId id)111 void JsScreenListener::OnDisconnect(ScreenId id)
112 {
113 std::lock_guard<std::mutex> lock(mtx_);
114 WLOGFI("JsScreenListener::OnDisconnect is called");
115 if (jsCallBack_.empty()) {
116 WLOGFE("JsScreenListener::OnDisconnect not register!");
117 return;
118 }
119 if (jsCallBack_.find(EVENT_DISCONNECT) == jsCallBack_.end()) {
120 WLOGE("JsScreenListener::OnDisconnect not this event, return");
121 return;
122 }
123
124 std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback> (
125 [=] (NativeEngine &engine, AsyncTask &task, int32_t status) {
126 NativeValue* argv[] = {CreateJsValue(*engine_, static_cast<uint32_t>(id))};
127 CallJsMethod(EVENT_DISCONNECT, argv, ArraySize(argv));
128 }
129 );
130
131 NativeReference* callback = nullptr;
132 std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
133 AsyncTask::Schedule("JsScreenListener::OnDisconnect", *engine_, std::make_unique<AsyncTask>(
134 callback, std::move(execute), std::move(complete)));
135 }
136
OnChange(ScreenId id)137 void JsScreenListener::OnChange(ScreenId id)
138 {
139 std::lock_guard<std::mutex> lock(mtx_);
140 WLOGFI("JsScreenListener::OnChange is called");
141 if (jsCallBack_.empty()) {
142 WLOGFE("JsScreenListener::OnChange not register!");
143 return;
144 }
145 if (jsCallBack_.find(EVENT_CHANGE) == jsCallBack_.end()) {
146 WLOGE("JsScreenListener::OnChange not this event, return");
147 return;
148 }
149
150 std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback> (
151 [=] (NativeEngine &engine, AsyncTask &task, int32_t status) {
152 NativeValue* argv[] = {CreateJsValue(*engine_, static_cast<uint32_t>(id))};
153 CallJsMethod(EVENT_CHANGE, argv, ArraySize(argv));
154 }
155 );
156
157 NativeReference* callback = nullptr;
158 std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
159 AsyncTask::Schedule("JsScreenListener::OnChange", *engine_, std::make_unique<AsyncTask>(
160 callback, std::move(execute), std::move(complete)));
161 }
162
CreateScreenIdArray(NativeEngine & engine,const std::vector<ScreenId> & data)163 NativeValue* JsScreenListener::CreateScreenIdArray(NativeEngine& engine, const std::vector<ScreenId>& data)
164 {
165 NativeValue* arrayValue = engine.CreateArray(data.size());
166 NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
167 if (array == nullptr) {
168 WLOGFE("Failed to create screenid array");
169 return engine.CreateUndefined();
170 }
171 uint32_t index = 0;
172 for (const auto& item : data) {
173 array->SetElement(index++, CreateJsValue(engine, static_cast<uint32_t>(item)));
174 }
175 return arrayValue;
176 }
177 } // namespace Rosen
178 } // namespace OHOS