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