• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "environment_callback.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "hitrace_meter.h"
20 #include "js_data_struct_converter.h"
21 #include "js_runtime_utils.h"
22 
23 namespace OHOS {
24 namespace AbilityRuntime {
JsEnvironmentCallback(napi_env env)25 JsEnvironmentCallback::JsEnvironmentCallback(napi_env env)
26     : env_(env)
27 {
28 }
29 
30 int32_t JsEnvironmentCallback::serialNumber_ = 0;
31 
CallConfigurationUpdatedInner(const std::string & methodName,const AppExecFwk::Configuration & config,const std::map<int32_t,std::shared_ptr<NativeReference>> & callbacks)32 void JsEnvironmentCallback::CallConfigurationUpdatedInner(const std::string &methodName,
33     const AppExecFwk::Configuration &config, const std::map<int32_t, std::shared_ptr<NativeReference>> &callbacks)
34 {
35     TAG_LOGD(AAFwkTag::APPKIT, "methodName = %{public}s", methodName.c_str());
36     for (auto &callback : callbacks) {
37         if (!callback.second) {
38             TAG_LOGE(AAFwkTag::APPKIT, "invalid jsCallback");
39             return;
40         }
41 
42         auto obj = callback.second->GetNapiValue();
43         if (!CheckTypeForNapiValue(env_, obj, napi_object)) {
44             TAG_LOGE(AAFwkTag::APPKIT, "get object failed");
45             return;
46         }
47 
48         napi_value method = nullptr;
49         napi_get_named_property(env_, obj, methodName.data(), &method);
50         if (method == nullptr) {
51             TAG_LOGE(AAFwkTag::APPKIT, "null method %{public}s", methodName.data());
52             return;
53         }
54 
55         napi_value argv[] = { CreateJsConfiguration(env_, config) };
56         napi_call_function(env_, obj, method, ArraySize(argv), argv, nullptr);
57     }
58 }
59 
OnConfigurationUpdated(const AppExecFwk::Configuration & config)60 void JsEnvironmentCallback::OnConfigurationUpdated(const AppExecFwk::Configuration &config)
61 {
62     std::weak_ptr<JsEnvironmentCallback> thisWeakPtr(shared_from_this());
63     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
64         [thisWeakPtr, config, callbacks = callbacks_, callbacksSync = callbacksSync_]
65         (napi_env env, NapiAsyncTask &task, int32_t status) {
66             std::shared_ptr<JsEnvironmentCallback> jsEnvCallback = thisWeakPtr.lock();
67             if (jsEnvCallback) {
68                 jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacks);
69                 jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacksSync);
70             }
71         }
72     );
73     napi_ref callback = nullptr;
74     std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
75     NapiAsyncTask::ScheduleLowQos("JsEnvironmentCallback::OnConfigurationUpdated",
76         env_, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
77 }
78 
CallMemoryLevelInner(const std::string & methodName,const int level,const std::map<int32_t,std::shared_ptr<NativeReference>> & callbacks)79 void JsEnvironmentCallback::CallMemoryLevelInner(const std::string &methodName, const int level,
80     const std::map<int32_t, std::shared_ptr<NativeReference>> &callbacks)
81 {
82     TAG_LOGD(AAFwkTag::APPKIT, "methodName = %{public}s", methodName.c_str());
83     for (auto &callback : callbacks) {
84         if (!callback.second) {
85             TAG_LOGE(AAFwkTag::APPKIT, "Invalid jsCallback");
86             return;
87         }
88 
89         auto obj = callback.second->GetNapiValue();
90         if (!CheckTypeForNapiValue(env_, obj, napi_object)) {
91             TAG_LOGE(AAFwkTag::APPKIT, "get object failed");
92             return;
93         }
94 
95         napi_value method = nullptr;
96         napi_get_named_property(env_, obj, methodName.data(), &method);
97         if (method == nullptr) {
98             TAG_LOGE(AAFwkTag::APPKIT, "null method %{public}s", methodName.data());
99             return;
100         }
101 
102         napi_value argv[] = { CreateJsValue(env_, level) };
103         napi_call_function(env_, obj, method, ArraySize(argv), argv, nullptr);
104     }
105 }
106 
OnMemoryLevel(const int level)107 void JsEnvironmentCallback::OnMemoryLevel(const int level)
108 {
109     std::weak_ptr<JsEnvironmentCallback> thisWeakPtr(shared_from_this());
110     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
111         [thisWeakPtr, level, callbacks = callbacks_, callbacksSync = callbacksSync_]
112         (napi_env env, NapiAsyncTask &task, int32_t status) {
113             std::shared_ptr<JsEnvironmentCallback> jsEnvCallback = thisWeakPtr.lock();
114             if (jsEnvCallback) {
115                 jsEnvCallback->CallMemoryLevelInner("onMemoryLevel", level, callbacks);
116                 jsEnvCallback->CallMemoryLevelInner("onMemoryLevel", level, callbacksSync);
117             }
118         }
119     );
120     napi_ref callback = nullptr;
121     std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
122     NapiAsyncTask::Schedule("JsEnvironmentCallback::OnMemoryLevel",
123         env_, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
124 }
125 
Register(napi_value jsCallback,bool isSync)126 int32_t JsEnvironmentCallback::Register(napi_value jsCallback, bool isSync)
127 {
128     if (env_ == nullptr) {
129         return -1;
130     }
131     int32_t callbackId = serialNumber_;
132     if (serialNumber_ < INT32_MAX) {
133         serialNumber_++;
134     } else {
135         serialNumber_ = 0;
136     }
137     napi_ref ref = nullptr;
138     napi_create_reference(env_, jsCallback, 1, &ref);
139     if (isSync) {
140         callbacksSync_.emplace(callbackId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
141     } else {
142         callbacks_.emplace(callbackId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
143     }
144     return callbackId;
145 }
146 
UnRegister(int32_t callbackId,bool isSync)147 bool JsEnvironmentCallback::UnRegister(int32_t callbackId, bool isSync)
148 {
149     TAG_LOGD(AAFwkTag::APPKIT, "callbackId : %{public}d", callbackId);
150     if (isSync) {
151         auto it = callbacksSync_.find(callbackId);
152         if (it == callbacksSync_.end()) {
153             TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d not in callbacksSync_", callbackId);
154             return false;
155         }
156         TAG_LOGD(AAFwkTag::APPKIT, "callbacksSync_.callbackId : %{public}d", it->first);
157         return callbacksSync_.erase(callbackId) == 1;
158     }
159     auto it = callbacks_.find(callbackId);
160     if (it == callbacks_.end()) {
161         TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d not in callbacks_", callbackId);
162         return false;
163     }
164     TAG_LOGD(AAFwkTag::APPKIT, "callbacks_.callbackId : %{public}d", it->first);
165     return callbacks_.erase(callbackId) == 1;
166 }
167 
IsEmpty() const168 bool JsEnvironmentCallback::IsEmpty() const
169 {
170     return callbacks_.empty() && callbacksSync_.empty();
171 }
172 }  // namespace AbilityRuntime
173 }  // namespace OHOS
174