1 /*
2 * Copyright (c) 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 "js_backgroundtask_subscriber.h"
17 #include "continuous_task_log.h"
18 #include "js_runtime_utils.h"
19 #include "iservice_registry.h"
20 #include "system_ability_definition.h"
21
22 namespace OHOS {
23 namespace BackgroundTaskMgr {
24 using namespace OHOS::AbilityRuntime;
25
JsBackgroudTaskSystemAbilityStatusChange(std::shared_ptr<JsBackgroundTaskSubscriber> subscriber)26 JsBackgroundTaskSubscriber::JsBackgroudTaskSystemAbilityStatusChange::JsBackgroudTaskSystemAbilityStatusChange(
27 std::shared_ptr<JsBackgroundTaskSubscriber> subscriber) : subscriber_(subscriber)
28 {
29 BGTASK_LOGD("JsBackgroudTaskSystemAbilityStatusChange constructor");
30 }
31
~JsBackgroudTaskSystemAbilityStatusChange()32 JsBackgroundTaskSubscriber::JsBackgroudTaskSystemAbilityStatusChange::~JsBackgroudTaskSystemAbilityStatusChange()
33 {
34 BGTASK_LOGD("~JsBackgroudTaskSystemAbilityStatusChange");
35 }
36
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)37 void JsBackgroundTaskSubscriber::JsBackgroudTaskSystemAbilityStatusChange::OnAddSystemAbility(
38 int32_t systemAbilityId, const std::string& deviceId)
39 {
40 BGTASK_LOGI("JsBackgroudTaskSystemAbilityStatusChange::OnAddSystemAbility");
41 if (systemAbilityId != BACKGROUND_TASK_MANAGER_SERVICE_ID) {
42 return;
43 }
44 auto subscriber = subscriber_.lock();
45 if (subscriber == nullptr) {
46 return;
47 }
48 if (!subscriber->needRestoreSubscribeStatus_) {
49 return;
50 }
51 ErrCode errCode = BackgroundTaskMgrHelper::SubscribeBackgroundTask(*subscriber);
52 if (errCode) {
53 BGTASK_LOGE("restore SubscribeBackgroundTask error");
54 } else {
55 BGTASK_LOGI("restore SubscribeBackgroundTask ok");
56 }
57 subscriber->needRestoreSubscribeStatus_ = false;
58 }
59
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)60 void JsBackgroundTaskSubscriber::JsBackgroudTaskSystemAbilityStatusChange::OnRemoveSystemAbility(
61 int32_t systemAbilityId, const std::string& deviceId)
62 {
63 if (systemAbilityId != BACKGROUND_TASK_MANAGER_SERVICE_ID) {
64 return;
65 }
66 BGTASK_LOGI("JsBackgroudTaskSystemAbilityStatusChange::OnRemoveSystemAbility");
67 auto subscriber = subscriber_.lock();
68 if (subscriber == nullptr) {
69 return;
70 }
71 if (!subscriber->IsEmpty()) {
72 subscriber->needRestoreSubscribeStatus_ = true;
73 BGTASK_LOGI("subscriber is not empty, need to restore");
74 } else {
75 BGTASK_LOGI("subscriber is empty, no need to restore");
76 }
77 }
78
JsBackgroundTaskSubscriber(napi_env env)79 JsBackgroundTaskSubscriber::JsBackgroundTaskSubscriber(napi_env env) : env_(env)
80 {
81 BGTASK_LOGD("JsBackgroundTaskSubscriber constructor");
82 }
83
~JsBackgroundTaskSubscriber()84 JsBackgroundTaskSubscriber::~JsBackgroundTaskSubscriber()
85 {
86 BGTASK_LOGD("~JsBackgroundTaskSubscriber");
87 }
88
SubscriberBgtaskSaStatusChange()89 void JsBackgroundTaskSubscriber::SubscriberBgtaskSaStatusChange()
90 {
91 if (jsSaListner_ != nullptr) {
92 return;
93 }
94 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
95 if (!systemManager) {
96 BGTASK_LOGI("ResSchedClient::Fail to get sa mgr client.");
97 return;
98 }
99 jsSaListner_ = new (std::nothrow) JsBackgroudTaskSystemAbilityStatusChange(shared_from_this());
100 if (jsSaListner_ == nullptr) {
101 BGTASK_LOGI("jsSaListner_ null");
102 return;
103 }
104 int32_t ret = systemManager->SubscribeSystemAbility(BACKGROUND_TASK_MANAGER_SERVICE_ID, jsSaListner_);
105 if (ret != ERR_OK) {
106 BGTASK_LOGI("sBackgroundTaskSubscriber::InitSaStatusListener error");
107 jsSaListner_ = nullptr;
108 }
109 BGTASK_LOGI("JsBackgroundTaskSubscriber::InitSaStatusListener ok");
110 }
111
UnSubscriberBgtaskSaStatusChange()112 void JsBackgroundTaskSubscriber::UnSubscriberBgtaskSaStatusChange()
113 {
114 if (jsSaListner_ == nullptr) {
115 return;
116 }
117 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
118 if (!systemManager) {
119 BGTASK_LOGE("GetSystemAbilityManager error");
120 return;
121 }
122 int32_t ret = systemManager->UnSubscribeSystemAbility(BACKGROUND_TASK_MANAGER_SERVICE_ID, jsSaListner_);
123 if (ret != ERR_OK) {
124 BGTASK_LOGE("UnSubscribeSystemAbility error");
125 } else {
126 BGTASK_LOGI("UnSubscribeSystemAbility ok");
127 }
128 jsSaListner_ = nullptr;
129 }
130
OnContinuousTaskStop(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)131 void JsBackgroundTaskSubscriber::OnContinuousTaskStop(
132 const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
133 {
134 BGTASK_LOGI("abilityname %{public}s continuousTaskId %{public}d cancelReason %{public}d",
135 continuousTaskCallbackInfo->GetAbilityName().c_str(),
136 continuousTaskCallbackInfo->GetContinuousTaskId(),
137 continuousTaskCallbackInfo->GetCancelReason());
138 std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
139 [self = weak_from_this(), continuousTaskCallbackInfo](napi_env env, NapiAsyncTask &task, int32_t status) {
140 auto jsObserver = self.lock();
141 if (jsObserver == nullptr) {
142 BGTASK_LOGE("null observer");
143 return;
144 }
145 BGTASK_LOGI("js thread %{public}s", continuousTaskCallbackInfo->GetAbilityName().c_str());
146 jsObserver->HandleOnContinuousTaskStop(continuousTaskCallbackInfo);
147 });
148 napi_ref callback = nullptr;
149 NapiAsyncTask::Schedule("JsBackgroundTaskSubscriber::OnContinuousTaskStop", env_,
150 std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
151 }
152
HandleOnContinuousTaskStop(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)153 void JsBackgroundTaskSubscriber::HandleOnContinuousTaskStop(
154 const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
155 {
156 BGTASK_LOGI("called");
157 std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
158 for (auto &item : jsObserverObjectSet_) {
159 napi_value jsCallbackObj = item->GetNapiValue();
160 napi_value jsContinuousTaskCancelInfo = nullptr;
161
162 napi_create_object(env_, &jsContinuousTaskCancelInfo);
163
164 napi_value value = nullptr;
165 napi_create_int32(env_, continuousTaskCallbackInfo->GetCancelReason(), &value);
166 napi_set_named_property(env_, jsContinuousTaskCancelInfo, "reason", value);
167
168 napi_create_int32(env_, continuousTaskCallbackInfo->GetContinuousTaskId(), &value);
169 napi_set_named_property(env_, jsContinuousTaskCancelInfo, "id", value);
170
171 napi_value argv[1] = { jsContinuousTaskCancelInfo };
172 napi_value callResult = nullptr;
173 napi_value undefined = nullptr;
174 napi_get_undefined(env_, &undefined);
175 napi_status status = napi_call_function(env_, undefined, jsCallbackObj, 1, argv, &callResult);
176 if (status != napi_ok) {
177 BGTASK_LOGE("call js func failed %{public}d.", status);
178 }
179 }
180 }
181
AddJsObserverObject(const napi_value & jsObserverObject)182 void JsBackgroundTaskSubscriber::AddJsObserverObject(const napi_value &jsObserverObject)
183 {
184 if (jsObserverObject == nullptr) {
185 BGTASK_LOGI("null observer");
186 return;
187 }
188
189 if (GetObserverObject(jsObserverObject) == nullptr) {
190 std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
191 napi_ref ref = nullptr;
192 napi_create_reference(env_, jsObserverObject, 1, &ref);
193 jsObserverObjectSet_.emplace(std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
194 BGTASK_LOGI("add observer, size %{public}d", static_cast<int32_t>(jsObserverObjectSet_.size()));
195 } else {
196 BGTASK_LOGI("observer exist");
197 }
198 }
199
GetObserverObject(const napi_value & jsObserverObject)200 std::shared_ptr<NativeReference> JsBackgroundTaskSubscriber::GetObserverObject(const napi_value &jsObserverObject)
201 {
202 if (jsObserverObject == nullptr) {
203 BGTASK_LOGI("null observer");
204 return nullptr;
205 }
206
207 std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
208 for (auto &observer : jsObserverObjectSet_) {
209 if (observer == nullptr) {
210 BGTASK_LOGI("null observer");
211 continue;
212 }
213
214 napi_value value = observer->GetNapiValue();
215 if (value == nullptr) {
216 BGTASK_LOGI("null value");
217 continue;
218 }
219
220 bool isEqual = false;
221 napi_strict_equals(env_, value, jsObserverObject, &isEqual);
222 if (isEqual) {
223 return observer;
224 }
225 }
226 return nullptr;
227 }
228
IsEmpty()229 bool JsBackgroundTaskSubscriber::IsEmpty()
230 {
231 std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
232 return jsObserverObjectSet_.empty();
233 }
234
RemoveAllJsObserverObjects()235 void JsBackgroundTaskSubscriber::RemoveAllJsObserverObjects()
236 {
237 std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
238 jsObserverObjectSet_.clear();
239 }
240
RemoveJsObserverObject(const napi_value & jsObserverObject)241 void JsBackgroundTaskSubscriber::RemoveJsObserverObject(const napi_value &jsObserverObject)
242 {
243 if (jsObserverObject == nullptr) {
244 BGTASK_LOGI("null observer");
245 return;
246 }
247
248 auto observer = GetObserverObject(jsObserverObject);
249 if (observer != nullptr) {
250 jsObserverObjectSet_.erase(observer);
251 }
252 }
253 } // BackgroundTaskMgr
254 } // OHOS