• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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("OnContinuousTaskStop 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("OnContinuousTaskStop js thread %{public}s",
146                 continuousTaskCallbackInfo->GetAbilityName().c_str());
147             jsObserver->HandleOnContinuousTaskStop(continuousTaskCallbackInfo);
148         });
149     napi_ref callback = nullptr;
150     NapiAsyncTask::Schedule("JsBackgroundTaskSubscriber::OnContinuousTaskStop", env_,
151         std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
152 }
153 
HandleOnContinuousTaskStop(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)154 void JsBackgroundTaskSubscriber::HandleOnContinuousTaskStop(
155     const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
156 {
157     BGTASK_LOGI("HandleOnContinuousTaskStop called");
158     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
159     auto iter = jsObserverObjectMap_.find("continuousTaskCancel");
160     if (iter == jsObserverObjectMap_.end()) {
161         BGTASK_LOGW("null callback Type");
162         return;
163     }
164     std::set<std::shared_ptr<NativeReference>> jsObserverObjectSet_ = iter->second;
165     for (auto &item : jsObserverObjectSet_) {
166         napi_value jsCallbackObj = item->GetNapiValue();
167         napi_value jsContinuousTaskCancelInfo = nullptr;
168 
169         napi_create_object(env_, &jsContinuousTaskCancelInfo);
170 
171         napi_value value = nullptr;
172         napi_create_int32(env_, continuousTaskCallbackInfo->GetCancelReason(), &value);
173         napi_set_named_property(env_, jsContinuousTaskCancelInfo, "reason", value);
174 
175         napi_create_int32(env_, continuousTaskCallbackInfo->GetContinuousTaskId(), &value);
176         napi_set_named_property(env_, jsContinuousTaskCancelInfo, "id", value);
177 
178         napi_value argv[1] = { jsContinuousTaskCancelInfo };
179         napi_value callResult = nullptr;
180         napi_value undefined = nullptr;
181         napi_get_undefined(env_, &undefined);
182         napi_status status = napi_call_function(env_, undefined, jsCallbackObj, 1, argv, &callResult);
183         if (status != napi_ok) {
184             BGTASK_LOGE("call js func failed %{public}d.", status);
185         }
186     }
187 }
188 
OnContinuousTaskSuspend(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)189 void JsBackgroundTaskSubscriber::OnContinuousTaskSuspend(
190     const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
191 {
192     BGTASK_LOGI("OnContinuousTaskSuspend abilityname: %{public}s, continuousTaskId: %{public}d,"
193         "suspendReason: %{public}d, suspendState: %{public}d", continuousTaskCallbackInfo->GetAbilityName().c_str(),
194         continuousTaskCallbackInfo->GetContinuousTaskId(), continuousTaskCallbackInfo->GetSuspendReason(),
195         continuousTaskCallbackInfo->GetSuspendState());
196     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
197         [self = weak_from_this(), continuousTaskCallbackInfo](napi_env env, NapiAsyncTask &task, int32_t status) {
198             auto jsObserver = self.lock();
199             if (jsObserver == nullptr) {
200                 BGTASK_LOGE("null observer");
201                 return;
202             }
203             BGTASK_LOGD("OnContinuousTaskSuspend js thread %{public}s",
204                 continuousTaskCallbackInfo->GetAbilityName().c_str());
205             jsObserver->HandleOnContinuousTaskSuspend(continuousTaskCallbackInfo);
206         });
207     napi_ref callback = nullptr;
208     NapiAsyncTask::Schedule("JsBackgroundTaskSubscriber::OnContinuousTaskSuspend", env_,
209         std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
210 }
211 
HandleOnContinuousTaskSuspend(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)212 void JsBackgroundTaskSubscriber::HandleOnContinuousTaskSuspend(
213     const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
214 {
215     BGTASK_LOGI("HandleOnContinuousTaskSuspend called");
216     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
217     auto iter = jsObserverObjectMap_.find("continuousTaskSuspend");
218     if (iter == jsObserverObjectMap_.end()) {
219         BGTASK_LOGW("null callback Type: continuousTaskSuspend");
220         return;
221     }
222     std::set<std::shared_ptr<NativeReference>> jsObserverObjectSet_ = iter->second;
223     for (auto &item : jsObserverObjectSet_) {
224         napi_value jsCallbackObj = item->GetNapiValue();
225         napi_value jsContinuousTaskSuspendInfo = nullptr;
226 
227         napi_create_object(env_, &jsContinuousTaskSuspendInfo);
228 
229         // set continuousTaskId
230         napi_value continuousTaskId = nullptr;
231         napi_create_int32(env_, continuousTaskCallbackInfo->GetContinuousTaskId(), &continuousTaskId);
232         napi_set_named_property(env_, jsContinuousTaskSuspendInfo, "continuousTaskId", continuousTaskId);
233 
234         // set suspendState
235         napi_value suspendState = nullptr;
236         napi_get_boolean(env_, continuousTaskCallbackInfo->GetSuspendState(), &suspendState);
237         napi_set_named_property(env_, jsContinuousTaskSuspendInfo, "suspendState", suspendState);
238 
239         // set suspendReason
240         napi_value suspendReason = nullptr;
241         napi_create_int32(env_, continuousTaskCallbackInfo->GetSuspendReason(), &suspendReason);
242         napi_set_named_property(env_, jsContinuousTaskSuspendInfo, "suspendReason", suspendReason);
243 
244         napi_value argv[1] = { jsContinuousTaskSuspendInfo };
245         napi_value callResult = nullptr;
246         napi_value undefined = nullptr;
247         napi_get_undefined(env_, &undefined);
248         napi_status status = napi_call_function(env_, undefined, jsCallbackObj, 1, argv, &callResult);
249         if (status != napi_ok) {
250             BGTASK_LOGE("call js func failed %{public}d.", status);
251         }
252     }
253 }
254 
OnContinuousTaskActive(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)255 void JsBackgroundTaskSubscriber::OnContinuousTaskActive(
256     const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
257 {
258     BGTASK_LOGI("OnContinuousTaskActive abilityname: %{public}s, continuousTaskId: %{public}d",
259         continuousTaskCallbackInfo->GetAbilityName().c_str(), continuousTaskCallbackInfo->GetContinuousTaskId());
260     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
261         [self = weak_from_this(), continuousTaskCallbackInfo](napi_env env, NapiAsyncTask &task, int32_t status) {
262             auto jsObserver = self.lock();
263             if (jsObserver == nullptr) {
264                 BGTASK_LOGE("null observer");
265                 return;
266             }
267             BGTASK_LOGI("OnContinuousTaskActive js thread %{public}s",
268                 continuousTaskCallbackInfo->GetAbilityName().c_str());
269             jsObserver->HandleOnContinuousTaskActive(continuousTaskCallbackInfo);
270         });
271     napi_ref callback = nullptr;
272     NapiAsyncTask::Schedule("JsBackgroundTaskSubscriber::OnContinuousTaskActive", env_,
273         std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
274 }
275 
HandleOnContinuousTaskActive(const std::shared_ptr<ContinuousTaskCallbackInfo> & continuousTaskCallbackInfo)276 void JsBackgroundTaskSubscriber::HandleOnContinuousTaskActive(
277     const std::shared_ptr<ContinuousTaskCallbackInfo> &continuousTaskCallbackInfo)
278 {
279     BGTASK_LOGI("HandleOnContinuousTaskActive called");
280     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
281     auto iter = jsObserverObjectMap_.find("continuousTaskActive");
282     if (iter == jsObserverObjectMap_.end()) {
283         BGTASK_LOGW("null callback Type: continuousTaskActive");
284         return;
285     }
286     std::set<std::shared_ptr<NativeReference>> jsObserverObjectSet_ = iter->second;
287     for (auto &item : jsObserverObjectSet_) {
288         napi_value jsCallbackObj = item->GetNapiValue();
289         napi_value jsContinuousTaskActiveInfo = nullptr;
290 
291         napi_create_object(env_, &jsContinuousTaskActiveInfo);
292 
293         // set continuousTaskId
294         napi_value continuousTaskId = nullptr;
295         napi_create_int32(env_, continuousTaskCallbackInfo->GetContinuousTaskId(), &continuousTaskId);
296         napi_set_named_property(env_, jsContinuousTaskActiveInfo, "id", continuousTaskId);
297 
298         napi_value argv[1] = { jsContinuousTaskActiveInfo };
299         napi_value callResult = nullptr;
300         napi_value undefined = nullptr;
301         napi_get_undefined(env_, &undefined);
302         napi_status status = napi_call_function(env_, undefined, jsCallbackObj, 1, argv, &callResult);
303         if (status != napi_ok) {
304             BGTASK_LOGE("call js func failed %{public}d.", status);
305         }
306     }
307 }
308 
AddJsObserverObject(const std::string cbType,const napi_value & jsObserverObject)309 void JsBackgroundTaskSubscriber::AddJsObserverObject(const std::string cbType, const napi_value &jsObserverObject)
310 {
311     if (jsObserverObject == nullptr) {
312         BGTASK_LOGI("null observer");
313         return;
314     }
315 
316     if (GetObserverObject(cbType, jsObserverObject) == nullptr) {
317         std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
318         napi_ref ref = nullptr;
319         napi_create_reference(env_, jsObserverObject, 1, &ref);
320         jsObserverObjectMap_[cbType].emplace(
321             std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
322         BGTASK_LOGI("add observer, type: %{public}s, size: %{public}d", cbType.c_str(),
323             static_cast<int32_t>(jsObserverObjectMap_[cbType].size()));
324     } else {
325         BGTASK_LOGI("observer exist");
326     }
327 }
328 
GetObserverObject(const std::string cbType,const napi_value & jsObserverObject)329 std::shared_ptr<NativeReference> JsBackgroundTaskSubscriber::GetObserverObject(
330     const std::string cbType, const napi_value &jsObserverObject)
331 {
332     if (jsObserverObject == nullptr) {
333         BGTASK_LOGI("null observer");
334         return nullptr;
335     }
336 
337     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
338     auto iter = jsObserverObjectMap_.find(cbType);
339     if (iter == jsObserverObjectMap_.end()) {
340         BGTASK_LOGW("null callback Type: %{public}s", cbType.c_str());
341         return nullptr;
342     }
343     std::set<std::shared_ptr<NativeReference>> jsObserverObjectSet_ = iter->second;
344     for (auto &observer : jsObserverObjectSet_) {
345         if (observer == nullptr) {
346             BGTASK_LOGI("null observer");
347             continue;
348         }
349 
350         napi_value value = observer->GetNapiValue();
351         if (value == nullptr) {
352             BGTASK_LOGI("null value");
353             continue;
354         }
355 
356         bool isEqual = false;
357         napi_strict_equals(env_, value, jsObserverObject, &isEqual);
358         if (isEqual) {
359             return observer;
360         }
361     }
362     return nullptr;
363 }
364 
IsEmpty()365 bool JsBackgroundTaskSubscriber::IsEmpty()
366 {
367     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
368     return jsObserverObjectMap_.empty();
369 }
370 
IsTypeEmpty(const std::string & cbType)371 bool JsBackgroundTaskSubscriber::IsTypeEmpty(const std::string &cbType)
372 {
373     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
374     auto iter = jsObserverObjectMap_.find(cbType);
375     return iter == jsObserverObjectMap_.end();
376 }
377 
RemoveJsObserverObjects(const std::string cbType)378 void JsBackgroundTaskSubscriber::RemoveJsObserverObjects(const std::string cbType)
379 {
380     std::lock_guard<std::mutex> lock(jsObserverObjectSetLock_);
381     auto iter = jsObserverObjectMap_.find(cbType);
382     if (iter != jsObserverObjectMap_.end()) {
383         jsObserverObjectMap_.erase(cbType);
384     }
385 }
386 
RemoveJsObserverObject(const std::string cbType,const napi_value & jsObserverObject)387 void JsBackgroundTaskSubscriber::RemoveJsObserverObject(const std::string cbType, const napi_value &jsObserverObject)
388 {
389     if (jsObserverObject == nullptr) {
390         BGTASK_LOGI("null observer");
391         return;
392     }
393 
394     auto observer = GetObserverObject(cbType, jsObserverObject);
395     if (observer != nullptr) {
396         jsObserverObjectMap_[cbType].erase(observer);
397     }
398 }
399 
SetFlag(uint32_t flag,bool isSubscriber)400 void JsBackgroundTaskSubscriber::SetFlag(uint32_t flag, bool isSubscriber)
401 {
402     std::lock_guard<std::mutex> lock(flagLock_);
403     if (isSubscriber) {
404         flag_ |= flag;
405     } else {
406         flag_ &= ~flag;
407     }
408 }
409 
GetFlag(int32_t & flag)410 void JsBackgroundTaskSubscriber::GetFlag(int32_t &flag)
411 {
412     std::lock_guard<std::mutex> lock(flagLock_);
413     flag = static_cast<int32_t>(flag_);
414 }
415 } // BackgroundTaskMgr
416 } // OHOS