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 "ability_lifecycle_callback.h"
17
18 #include "hilog_wrapper.h"
19 #include "js_runtime_utils.h"
20
21 namespace OHOS {
22 namespace AbilityRuntime {
JsAbilityLifecycleCallback(NativeEngine * engine)23 JsAbilityLifecycleCallback::JsAbilityLifecycleCallback(NativeEngine* engine)
24 : engine_(engine)
25 {
26 }
27
28 int32_t JsAbilityLifecycleCallback::serialNumber_ = 0;
29
CallJsMethodInnerCommon(const std::string & methodName,const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage,const std::map<int32_t,std::shared_ptr<NativeReference>> callbacks)30 void JsAbilityLifecycleCallback::CallJsMethodInnerCommon(const std::string &methodName,
31 const std::shared_ptr<NativeReference> &ability, const std::shared_ptr<NativeReference> &windowStage,
32 const std::map<int32_t, std::shared_ptr<NativeReference>> callbacks)
33 {
34 auto nativeAbilityObj = engine_->CreateNull();
35 if (ability != nullptr) {
36 nativeAbilityObj = ability->Get();
37 }
38
39 bool isWindowStage = false;
40 auto nativeWindowStageObj = engine_->CreateNull();
41 if (windowStage != nullptr) {
42 nativeWindowStageObj = windowStage->Get();
43 isWindowStage = true;
44 }
45
46 for (auto &callback : callbacks) {
47 if (!callback.second) {
48 HILOG_ERROR("CallJsMethodInnerCommon, Invalid jsCallback");
49 return;
50 }
51
52 auto value = callback.second->Get();
53 auto obj = ConvertNativeValueTo<NativeObject>(value);
54 if (obj == nullptr) {
55 HILOG_ERROR("CallJsMethodInnerCommon, Failed to get object");
56 return;
57 }
58
59 auto method = obj->GetProperty(methodName.data());
60 if (method == nullptr) {
61 HILOG_ERROR("CallJsMethodInnerCommon, Failed to get %{public}s from object", methodName.data());
62 return;
63 }
64
65 if (!isWindowStage) {
66 NativeValue *argv[] = { nativeAbilityObj };
67 engine_->CallFunction(value, method, argv, ArraySize(argv));
68 } else {
69 NativeValue *argv[] = { nativeAbilityObj, nativeWindowStageObj };
70 engine_->CallFunction(value, method, argv, ArraySize(argv));
71 }
72 }
73 }
74
CallJsMethod(const std::string & methodName,const std::shared_ptr<NativeReference> & ability)75 void JsAbilityLifecycleCallback::CallJsMethod(
76 const std::string &methodName, const std::shared_ptr<NativeReference> &ability)
77 {
78 HILOG_DEBUG("CallJsMethod methodName = %{public}s", methodName.c_str());
79 if (!ability) {
80 HILOG_ERROR("ability is nullptr");
81 return;
82 }
83 std::weak_ptr<JsAbilityLifecycleCallback> thisWeakPtr(shared_from_this());
84 std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback>(
85 [thisWeakPtr, methodName, ability, callbacks = callbacks_, callbacksSync = callbacksSync_]
86 (NativeEngine &engine, AsyncTask &task, int32_t status) {
87 std::shared_ptr<JsAbilityLifecycleCallback> jsCallback = thisWeakPtr.lock();
88 if (jsCallback) {
89 jsCallback->CallJsMethodInnerCommon(methodName, ability, nullptr, callbacks);
90 jsCallback->CallJsMethodInnerCommon(methodName, ability, nullptr, callbacksSync);
91 }
92 }
93 );
94 NativeReference *callback = nullptr;
95 std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
96 AsyncTask::Schedule("JsAbilityLifecycleCallback::CallJsMethod:" + methodName,
97 *engine_, std::make_unique<AsyncTask>(callback, std::move(execute), std::move(complete)));
98 }
99
CallWindowStageJsMethod(const std::string & methodName,const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)100 void JsAbilityLifecycleCallback::CallWindowStageJsMethod(const std::string &methodName,
101 const std::shared_ptr<NativeReference> &ability, const std::shared_ptr<NativeReference> &windowStage)
102 {
103 HILOG_DEBUG("CallWindowStageJsMethod methodName = %{public}s", methodName.c_str());
104 if (!ability || !windowStage) {
105 HILOG_ERROR("ability or windowStage is nullptr");
106 return;
107 }
108 std::weak_ptr<JsAbilityLifecycleCallback> thisWeakPtr(shared_from_this());
109 std::unique_ptr<AsyncTask::CompleteCallback> complete = std::make_unique<AsyncTask::CompleteCallback>(
110 [thisWeakPtr, methodName, ability, windowStage, callbacks = callbacks_, callbacksSync = callbacksSync_]
111 (NativeEngine &engine, AsyncTask &task, int32_t status) {
112 std::shared_ptr<JsAbilityLifecycleCallback> jsCallback = thisWeakPtr.lock();
113 if (jsCallback) {
114 jsCallback->CallJsMethodInnerCommon(methodName, ability, windowStage, callbacks);
115 jsCallback->CallJsMethodInnerCommon(methodName, ability, windowStage, callbacksSync);
116 }
117 }
118 );
119 NativeReference *callback = nullptr;
120 std::unique_ptr<AsyncTask::ExecuteCallback> execute = nullptr;
121 AsyncTask::Schedule("JsAbilityLifecycleCallback::CallWindowStageJsMethod:" + methodName,
122 *engine_, std::make_unique<AsyncTask>(callback, std::move(execute), std::move(complete)));
123 }
124
OnAbilityCreate(const std::shared_ptr<NativeReference> & ability)125 void JsAbilityLifecycleCallback::OnAbilityCreate(const std::shared_ptr<NativeReference> &ability)
126 {
127 CallJsMethod("onAbilityCreate", ability);
128 }
129
OnWindowStageCreate(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)130 void JsAbilityLifecycleCallback::OnWindowStageCreate(const std::shared_ptr<NativeReference> &ability,
131 const std::shared_ptr<NativeReference> &windowStage)
132 {
133 CallWindowStageJsMethod("onWindowStageCreate", ability, windowStage);
134 }
135
OnWindowStageDestroy(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)136 void JsAbilityLifecycleCallback::OnWindowStageDestroy(const std::shared_ptr<NativeReference> &ability,
137 const std::shared_ptr<NativeReference> &windowStage)
138 {
139 CallWindowStageJsMethod("onWindowStageDestroy", ability, windowStage);
140 }
141
OnWindowStageActive(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)142 void JsAbilityLifecycleCallback::OnWindowStageActive(const std::shared_ptr<NativeReference> &ability,
143 const std::shared_ptr<NativeReference> &windowStage)
144 {
145 CallWindowStageJsMethod("onWindowStageActive", ability, windowStage);
146 }
147
OnWindowStageInactive(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)148 void JsAbilityLifecycleCallback::OnWindowStageInactive(const std::shared_ptr<NativeReference> &ability,
149 const std::shared_ptr<NativeReference> &windowStage)
150 {
151 CallWindowStageJsMethod("onWindowStageInactive", ability, windowStage);
152 }
153
OnAbilityDestroy(const std::shared_ptr<NativeReference> & ability)154 void JsAbilityLifecycleCallback::OnAbilityDestroy(const std::shared_ptr<NativeReference> &ability)
155 {
156 CallJsMethod("onAbilityDestroy", ability);
157 }
158
OnAbilityForeground(const std::shared_ptr<NativeReference> & ability)159 void JsAbilityLifecycleCallback::OnAbilityForeground(const std::shared_ptr<NativeReference> &ability)
160 {
161 CallJsMethod("onAbilityForeground", ability);
162 }
163
OnAbilityBackground(const std::shared_ptr<NativeReference> & ability)164 void JsAbilityLifecycleCallback::OnAbilityBackground(const std::shared_ptr<NativeReference> &ability)
165 {
166 CallJsMethod("onAbilityBackground", ability);
167 }
168
OnAbilityContinue(const std::shared_ptr<NativeReference> & ability)169 void JsAbilityLifecycleCallback::OnAbilityContinue(const std::shared_ptr<NativeReference> &ability)
170 {
171 CallJsMethod("onAbilityContinue", ability);
172 }
173
Register(NativeValue * jsCallback,bool isSync)174 int32_t JsAbilityLifecycleCallback::Register(NativeValue *jsCallback, bool isSync)
175 {
176 if (engine_ == nullptr) {
177 return -1;
178 }
179 int32_t callbackId = serialNumber_;
180 if (serialNumber_ < INT32_MAX) {
181 serialNumber_++;
182 } else {
183 serialNumber_ = 0;
184 }
185 if (isSync) {
186 callbacksSync_.emplace(callbackId, std::shared_ptr<NativeReference>(engine_->CreateReference(jsCallback, 1)));
187 } else {
188 callbacks_.emplace(callbackId, std::shared_ptr<NativeReference>(engine_->CreateReference(jsCallback, 1)));
189 }
190 return callbackId;
191 }
192
UnRegister(int32_t callbackId,bool isSync)193 bool JsAbilityLifecycleCallback::UnRegister(int32_t callbackId, bool isSync)
194 {
195 HILOG_INFO("UnRegister called, callbackId : %{public}d", callbackId);
196 if (isSync) {
197 auto it = callbacksSync_.find(callbackId);
198 if (it == callbacksSync_.end()) {
199 HILOG_ERROR("UnRegister callbackId: %{public}d is not in callbacksSync_", callbackId);
200 return false;
201 }
202 return callbacksSync_.erase(callbackId) == 1;
203 }
204 auto it = callbacks_.find(callbackId);
205 if (it == callbacks_.end()) {
206 HILOG_ERROR("UnRegister callbackId: %{public}d is not in callbacks_", callbackId);
207 return false;
208 }
209 return callbacks_.erase(callbackId) == 1;
210 }
211
IsEmpty() const212 bool JsAbilityLifecycleCallback::IsEmpty() const
213 {
214 return callbacks_.empty() && callbacksSync_.empty();
215 }
216 } // namespace AbilityRuntime
217 } // namespace OHOS
218