• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include <hitrace_meter.h>
17 
18 #include "js_screen_listener.h"
19 #include "js_runtime_utils.h"
20 #include "window_manager_hilog.h"
21 #include "js_screen.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 using namespace AbilityRuntime;
26 inline uint32_t SCREEN_DISCONNECT_TYPE = 0;
27 inline uint32_t SCREEN_CONNECT_TYPE = 1;
28 
JsScreenListener(napi_env env)29 JsScreenListener::JsScreenListener(napi_env env) : env_(env), weakRef_(wptr<JsScreenListener> (this))
30 {
31     TLOGI(WmsLogTag::DMS, "Constructor execution");
32     napi_add_env_cleanup_hook(env_, CleanEnv, this);
33 }
34 
~JsScreenListener()35 JsScreenListener::~JsScreenListener()
36 {
37     TLOGI(WmsLogTag::DMS, "Destructor execution");
38     napi_remove_env_cleanup_hook(env_, CleanEnv, this);
39     env_ = nullptr;
40 }
41 
CleanEnv(void * obj)42 void JsScreenListener::CleanEnv(void* obj)
43 {
44     JsScreenListener* thisObj = reinterpret_cast<JsScreenListener*>(obj);
45     if (!thisObj) {
46         TLOGE(WmsLogTag::DMS, "obj is nullptr");
47         return;
48     }
49     TLOGI(WmsLogTag::DMS, "env_ is invalid, set to nullptr");
50     thisObj->env_ = nullptr;
51 }
52 
AddCallback(const std::string & type,napi_value jsListenerObject)53 void JsScreenListener::AddCallback(const std::string& type, napi_value jsListenerObject)
54 {
55     TLOGI(WmsLogTag::DMS, "called");
56     std::lock_guard<std::mutex> lock(mtx_);
57     std::unique_ptr<NativeReference> callbackRef;
58     napi_ref result = nullptr;
59     napi_create_reference(env_, jsListenerObject, 1, &result);
60     callbackRef.reset(reinterpret_cast<NativeReference*>(result));
61     jsCallBack_[type].emplace_back(std::move(callbackRef));
62     TLOGI(WmsLogTag::DMS, "success jsCallBack_ size: %{public}u!",
63         static_cast<uint32_t>(jsCallBack_[type].size()));
64 }
65 
RemoveAllCallback()66 void JsScreenListener::RemoveAllCallback()
67 {
68     std::lock_guard<std::mutex> lock(mtx_);
69     jsCallBack_.clear();
70 }
71 
RemoveCallback(napi_env env,const std::string & type,napi_value jsListenerObject)72 void JsScreenListener::RemoveCallback(napi_env env, const std::string& type, napi_value jsListenerObject)
73 {
74     std::lock_guard<std::mutex> lock(mtx_);
75     auto it = jsCallBack_.find(type);
76     if (it == jsCallBack_.end()) {
77         TLOGE(WmsLogTag::DMS, "no callback to remove");
78         return;
79     }
80     auto& listeners = it->second;
81     for (auto iter = listeners.begin(); iter != listeners.end();) {
82         bool isEquals = false;
83         napi_strict_equals(env, jsListenerObject, (*iter)->GetNapiValue(), &isEquals);
84         if (isEquals) {
85             listeners.erase(iter);
86         } else {
87             iter++;
88         }
89     }
90     TLOGI(WmsLogTag::DMS, "success jsCallBack_ size: %{public}u!",
91         static_cast<uint32_t>(listeners.size()));
92 }
93 
CallJsMethod(const std::string & methodName,napi_value const * argv,size_t argc)94 void JsScreenListener::CallJsMethod(const std::string& methodName, napi_value const * argv, size_t argc)
95 {
96     if (methodName.empty()) {
97         TLOGE(WmsLogTag::DMS, "empty method name str, call method failed");
98         return;
99     }
100     TLOGD(WmsLogTag::DMS, "CallJsMethod methodName = %{public}s", methodName.c_str());
101     if (env_ == nullptr) {
102         TLOGE(WmsLogTag::DMS, "env_ nullptr");
103         return;
104     }
105     for (auto& callback : jsCallBack_[methodName]) {
106         napi_value method = callback->GetNapiValue();
107         if (method == nullptr) {
108             TLOGE(WmsLogTag::DMS, "Failed to get method callback from object");
109             continue;
110         }
111         napi_call_function(env_, NapiGetUndefined(env_), method, argc, argv, nullptr);
112     }
113 }
114 
OnConnect(ScreenId id)115 void JsScreenListener::OnConnect(ScreenId id)
116 {
117     std::lock_guard<std::mutex> lock(mtx_);
118     TLOGI(WmsLogTag::DMS, "called");
119     if (jsCallBack_.empty()) {
120         TLOGE(WmsLogTag::DMS, "not register!");
121         return;
122     }
123     if (jsCallBack_.find(EVENT_CONNECT) == jsCallBack_.end()) {
124         TLOGE(WmsLogTag::DMS, "not this event, return");
125         return;
126     }
127     auto napiTask = [self = weakRef_, id, env = env_] () {
128         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsScreenListener::OnConnect");
129         auto thisListener = self.promote();
130         if (thisListener == nullptr || env == nullptr) {
131             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
132             return;
133         }
134         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
135         thisListener->CallJsMethod(EVENT_CONNECT, argv, ArraySize(argv));
136     };
137 
138     if (env_ != nullptr) {
139         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnConnect");
140         if (ret != napi_status::napi_ok) {
141             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
142         }
143     } else {
144         TLOGE(WmsLogTag::DMS, "env is nullptr");
145     }
146 }
147 
OnDisconnect(ScreenId id)148 void JsScreenListener::OnDisconnect(ScreenId id)
149 {
150     std::lock_guard<std::mutex> lock(mtx_);
151     TLOGI(WmsLogTag::DMS, "called");
152     if (jsCallBack_.empty()) {
153         TLOGE(WmsLogTag::DMS, "not register!");
154         return;
155     }
156     if (jsCallBack_.find(EVENT_DISCONNECT) == jsCallBack_.end()) {
157         TLOGE(WmsLogTag::DMS, "not this event, return");
158         return;
159     }
160     auto napiTask = [self = weakRef_, id, env = env_] () {
161         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsScreenListener::OnDisconnect");
162         auto thisListener = self.promote();
163         if (thisListener == nullptr || env == nullptr) {
164             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
165             return;
166         }
167         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
168         thisListener->CallJsMethod(EVENT_DISCONNECT, argv, ArraySize(argv));
169     };
170 
171     if (env_ != nullptr) {
172         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnDisconnect");
173         if (ret != napi_status::napi_ok) {
174             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
175         }
176     } else {
177         TLOGE(WmsLogTag::DMS, "env is nullptr");
178     }
179 }
180 
OnChange(ScreenId id)181 void JsScreenListener::OnChange(ScreenId id)
182 {
183     std::lock_guard<std::mutex> lock(mtx_);
184     TLOGI(WmsLogTag::DMS, "called");
185     if (jsCallBack_.empty()) {
186         TLOGE(WmsLogTag::DMS, "not register!");
187         return;
188     }
189     if (jsCallBack_.find(EVENT_CHANGE) == jsCallBack_.end()) {
190         TLOGE(WmsLogTag::DMS, "not this event, return");
191         return;
192     }
193     auto napiTask = [self = weakRef_, id, env = env_] () {
194         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsScreenListener::OnChange");
195         auto thisListener = self.promote();
196         if (thisListener == nullptr || env == nullptr) {
197             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
198             return;
199         }
200         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
201         thisListener->CallJsMethod(EVENT_CHANGE, argv, ArraySize(argv));
202     };
203 
204     if (env_ != nullptr) {
205         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnChange");
206         if (ret != napi_status::napi_ok) {
207             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
208         }
209     } else {
210         TLOGE(WmsLogTag::DMS, "env is nullptr");
211     }
212 }
213 
CreateScreenIdArray(napi_env env,const std::vector<ScreenId> & data)214 napi_value JsScreenListener::CreateScreenIdArray(napi_env env, const std::vector<ScreenId>& data)
215 {
216     napi_value arrayValue = nullptr;
217     napi_create_array_with_length(env, data.size(), &arrayValue);
218     if (arrayValue == nullptr) {
219         TLOGE(WmsLogTag::DMS, "Failed to create screenid array");
220         return NapiGetUndefined(env);
221     }
222     uint32_t index = 0;
223     for (const auto& item : data) {
224         napi_set_element(env, arrayValue, index++, CreateJsValue(env, static_cast<uint32_t>(item)));
225     }
226     return arrayValue;
227 }
228 } // namespace Rosen
229 } // namespace OHOS
230