• 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("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