1 /*
2 * Copyright (c) 2023-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_ability_foreground_state_observer.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "js_runtime_utils.h"
20
21 namespace OHOS {
22 namespace AbilityRuntime {
23 namespace {
24 constexpr size_t ARGC_ONE = 1;
25 }
JSAbilityForegroundStateObserver(napi_env env)26 JSAbilityForegroundStateObserver::JSAbilityForegroundStateObserver(napi_env env) : env_(env) {}
27
CleanUp(void * data)28 void JSAbilityForegroundStateObserver::CleanUp(void *data)
29 {
30 TAG_LOGI(AAFwkTag::ABILITYMGR, "CleanUp");
31 auto observerInstance = reinterpret_cast<wptr<JSAbilityForegroundStateObserver> *>(data);
32 if (observerInstance == nullptr) {
33 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
34 return;
35 }
36 auto observerRef = observerInstance->promote();
37 if (observerRef) {
38 observerRef->RemoveAllJsObserverObject();
39 observerRef->SetValid(false);
40 observerRef->env_ = nullptr;
41 }
42 delete observerInstance;
43 }
44
OnAbilityStateChanged(const AbilityStateData & abilityStateData)45 void JSAbilityForegroundStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData)
46 {
47 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
48 if (!valid_) {
49 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid appms");
50 return;
51 }
52 wptr<JSAbilityForegroundStateObserver> jsObserver = this;
53 std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
54 [jsObserver, abilityStateData](napi_env env, NapiAsyncTask &task, int32_t status) {
55 sptr<JSAbilityForegroundStateObserver> jsObserverSptr = jsObserver.promote();
56 if (jsObserverSptr == nullptr) {
57 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
58 return;
59 }
60 jsObserverSptr->HandleOnAbilityStateChanged(abilityStateData);
61 });
62 napi_ref callback = nullptr;
63 NapiAsyncTask::Schedule("JSAbilityForegroundStateObserver::OnAbilityStateChanged", env_,
64 std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
65 }
66
HandleOnAbilityStateChanged(const AbilityStateData & abilityStateData)67 void JSAbilityForegroundStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData)
68 {
69 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
70 for (auto &item : jsObserverObjectSet_) {
71 if (item == nullptr) {
72 continue;
73 }
74 napi_value obj = item->GetNapiValue();
75 napi_value argv[] = { CreateJsAbilityStateData(env_, abilityStateData) };
76 CallJsFunction(obj, "onAbilityStateChanged", argv, ARGC_ONE);
77 }
78 }
79
CallJsFunction(const napi_value & value,const char * methodName,const napi_value * argv,const size_t argc)80 void JSAbilityForegroundStateObserver::CallJsFunction(
81 const napi_value &value, const char *methodName, const napi_value *argv, const size_t argc)
82 {
83 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
84 if (value == nullptr) {
85 TAG_LOGE(AAFwkTag::ABILITYMGR, "null value");
86 return;
87 }
88
89 napi_value method = nullptr;
90 napi_get_named_property(env_, value, methodName, &method);
91 if (method == nullptr) {
92 TAG_LOGE(AAFwkTag::ABILITYMGR, "null method");
93 return;
94 }
95 napi_value callResult = nullptr;
96 napi_status status = napi_call_function(env_, value, method, argc, argv, &callResult);
97 if (status != napi_ok) {
98 TAG_LOGE(AAFwkTag::ABILITYMGR, "call js func failed: %{public}d", status);
99 }
100 TAG_LOGD(AAFwkTag::ABILITYMGR, "end");
101 }
102
IsObserverObjectExsit(const napi_value & jsObserverObject)103 bool JSAbilityForegroundStateObserver::IsObserverObjectExsit(const napi_value &jsObserverObject)
104 {
105 if (jsObserverObject == nullptr) {
106 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
107 return false;
108 }
109
110 if (GetObserverObject(jsObserverObject) == nullptr) {
111 TAG_LOGD(AAFwkTag::ABILITYMGR, "observer not exist");
112 return false;
113 }
114 return true;
115 }
116
AddJsObserverObject(const napi_value & jsObserverObject)117 void JSAbilityForegroundStateObserver::AddJsObserverObject(const napi_value &jsObserverObject)
118 {
119 if (jsObserverObject == nullptr) {
120 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
121 return;
122 }
123
124 if (IsObserverObjectExsit(jsObserverObject)) {
125 TAG_LOGD(AAFwkTag::ABILITYMGR, "observer not exist");
126 return;
127 }
128 napi_ref ref = nullptr;
129 napi_create_reference(env_, jsObserverObject, 1, &ref);
130 jsObserverObjectSet_.emplace(std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
131 }
132
RemoveJsObserverObject(const napi_value & jsObserverObject)133 void JSAbilityForegroundStateObserver::RemoveJsObserverObject(const napi_value &jsObserverObject)
134 {
135 if (jsObserverObject == nullptr) {
136 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
137 return;
138 }
139
140 auto observer = GetObserverObject(jsObserverObject);
141 if (observer != nullptr) {
142 jsObserverObjectSet_.erase(observer);
143 }
144 }
145
RemoveAllJsObserverObject()146 void JSAbilityForegroundStateObserver::RemoveAllJsObserverObject()
147 {
148 if (!jsObserverObjectSet_.empty()) {
149 jsObserverObjectSet_.clear();
150 }
151 }
152
GetObserverObject(const napi_value & jsObserverObject)153 std::shared_ptr<NativeReference> JSAbilityForegroundStateObserver::GetObserverObject(const napi_value &jsObserverObject)
154 {
155 if (jsObserverObject == nullptr) {
156 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
157 return nullptr;
158 }
159 for (auto &observer : jsObserverObjectSet_) {
160 if (observer == nullptr) {
161 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
162 continue;
163 }
164
165 napi_value value = observer->GetNapiValue();
166 if (value == nullptr) {
167 TAG_LOGE(AAFwkTag::ABILITYMGR, "get object failed");
168 continue;
169 }
170
171 bool isEqual = false;
172 napi_strict_equals(env_, value, jsObserverObject, &isEqual);
173 if (isEqual) {
174 return observer;
175 }
176 }
177 return nullptr;
178 }
179
SetValid(const bool valid)180 void JSAbilityForegroundStateObserver::SetValid(const bool valid)
181 {
182 valid_ = valid;
183 }
184
IsEmpty()185 bool JSAbilityForegroundStateObserver::IsEmpty()
186 {
187 return jsObserverObjectSet_.empty();
188 }
189 } // namespace AbilityRuntime
190 } // namespace OHOS
191