1 /*
2 * Copyright (c) 2025 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 "ets_free_install_observer.h"
17
18 #include "ability_business_error.h"
19 #include "ani_common_ability_result.h"
20 #include "ani_common_util.h"
21 #include "ani_common_want.h"
22 #include "hilog_tag_wrapper.h"
23 #include "hitrace_meter.h"
24
25 namespace OHOS {
26 namespace AbilityRuntime {
EtsFreeInstallObserver(ani_vm * etsVm)27 EtsFreeInstallObserver::EtsFreeInstallObserver(ani_vm *etsVm) : etsVm_(etsVm) {}
28
~EtsFreeInstallObserver()29 EtsFreeInstallObserver::~EtsFreeInstallObserver()
30 {
31 ani_env *env = nullptr;
32 ani_status status = ANI_ERROR;
33 ani_option interopEnabled { "--interop=disable", nullptr };
34 ani_options aniArgs { 1, &interopEnabled };
35 if (etsVm_ == nullptr) {
36 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null etsVm_");
37 return;
38 }
39 if ((etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) {
40 TAG_LOGE(AAFwkTag::FREE_INSTALL, "status: %{public}d", status);
41 return;
42 }
43 if (env == nullptr) {
44 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null env");
45 return;
46 }
47 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end();) {
48 env->GlobalReference_Delete(it->callback);
49 it++;
50 }
51 if ((status = etsVm_->DetachCurrentThread()) != ANI_OK) {
52 TAG_LOGE(AAFwkTag::FREE_INSTALL, "status: %{public}d", status);
53 }
54 }
55
OnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,int32_t resultCode)56 void EtsFreeInstallObserver::OnInstallFinished(
57 const std::string &bundleName, const std::string &abilityName, const std::string &startTime, int32_t resultCode)
58 {
59 TAG_LOGD(AAFwkTag::FREE_INSTALL, "OnInstallFinished");
60 HandleOnInstallFinished(bundleName, abilityName, startTime, resultCode);
61 }
62
OnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,ani_object abilityResult)63 void EtsFreeInstallObserver::OnInstallFinished(const std::string &bundleName, const std::string &abilityName,
64 const std::string &startTime, ani_object abilityResult)
65 {
66 TAG_LOGD(AAFwkTag::FREE_INSTALL, "OnInstallFinished");
67 std::vector<ani_object> callbacks;
68 {
69 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
70 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end();) {
71 if ((it->bundleName != bundleName) || (it->abilityName != abilityName) || (it->startTime != startTime)
72 || (it->callback == nullptr) || (!it->isAbilityResult)) {
73 it++;
74 continue;
75 }
76 callbacks.emplace_back(it->callback);
77 it = etsObserverObjectList_.erase(it);
78 TAG_LOGD(AAFwkTag::FREE_INSTALL, "etsObserverObjectList_ size:%{public}zu", etsObserverObjectList_.size());
79 }
80 }
81
82 for (auto& callback : callbacks) {
83 CallCallback(callback, abilityResult);
84 FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
85 }
86 }
87
OnInstallFinishedByUrl(const std::string & startTime,const std::string & url,int32_t resultCode)88 void EtsFreeInstallObserver::OnInstallFinishedByUrl(
89 const std::string &startTime, const std::string &url, int32_t resultCode)
90 {
91 TAG_LOGD(AAFwkTag::FREE_INSTALL, "OnInstallFinishedByUrl");
92 HandleOnInstallFinishedByUrl(startTime, url, resultCode);
93 }
94
HandleOnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,int32_t resultCode)95 void EtsFreeInstallObserver::HandleOnInstallFinished(
96 const std::string &bundleName, const std::string &abilityName, const std::string &startTime, int32_t resultCode)
97 {
98 std::vector<ani_object> callbacks;
99 {
100 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
101 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end();) {
102 if ((it->bundleName != bundleName) || (it->abilityName != abilityName) || (it->startTime != startTime) ||
103 (it->callback == nullptr) || (it->isAbilityResult && resultCode == ERR_OK)) {
104 it++;
105 continue;
106 }
107 callbacks.emplace_back(it->callback);
108 it = etsObserverObjectList_.erase(it);
109 }
110 }
111
112 for (auto& callback : callbacks) {
113 CallCallback(callback, resultCode);
114 FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
115 }
116 }
117
HandleOnInstallFinishedByUrl(const std::string & startTime,const std::string & url,int32_t resultCode)118 void EtsFreeInstallObserver::HandleOnInstallFinishedByUrl(
119 const std::string &startTime, const std::string &url, int32_t resultCode)
120 {
121 std::vector<ani_object> callbacks;
122 {
123 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
124 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end();) {
125 if ((it->startTime != startTime) || (it->url != url) || (it->callback == nullptr)) {
126 it++;
127 continue;
128 }
129 callbacks.emplace_back(it->callback);
130 it = etsObserverObjectList_.erase(it);
131 }
132 }
133
134 for (auto& callback : callbacks) {
135 CallCallback(callback, resultCode);
136 FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
137 }
138 }
139
CallCallback(ani_object callback,int32_t resultCode)140 void EtsFreeInstallObserver::CallCallback(ani_object callback, int32_t resultCode)
141 {
142 TAG_LOGD(AAFwkTag::FREE_INSTALL, "CallCallback");
143 if (callback == nullptr) {
144 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null callback");
145 return;
146 }
147 if (etsVm_ == nullptr) {
148 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null etsVm");
149 return;
150 }
151 ani_env *env = nullptr;
152 ani_status status = ANI_ERROR;
153 ani_option interopEnabled { "--interop=disable", nullptr };
154 ani_options aniArgs { 1, &interopEnabled };
155 if ((status = etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) {
156 TAG_LOGE(AAFwkTag::FREE_INSTALL, "Failed to getEnv, status: %{public}d", status);
157 } else if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) {
158 TAG_LOGE(AAFwkTag::FREE_INSTALL, "Failed to getEnv, status: %{public}d", status);
159 return;
160 }
161 ani_object aniObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK);
162 if (resultCode != ERR_OK) {
163 aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, resultCode);
164 }
165 AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr);
166 env->GlobalReference_Delete(callback);
167 if ((status = etsVm_->DetachCurrentThread()) != ANI_OK) {
168 TAG_LOGE(AAFwkTag::FREE_INSTALL, "status: %{public}d", status);
169 }
170 }
171
CallCallback(ani_object callback,ani_object abilityResult)172 void EtsFreeInstallObserver::CallCallback(ani_object callback, ani_object abilityResult)
173 {
174 TAG_LOGD(AAFwkTag::FREE_INSTALL, "CallCallback");
175 if (abilityResult == nullptr) {
176 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null abilityResult");
177 return;
178 }
179 if (callback == nullptr) {
180 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null callback");
181 return;
182 }
183 if (etsVm_ == nullptr) {
184 TAG_LOGE(AAFwkTag::FREE_INSTALL, "null etsVm");
185 return;
186 }
187 ani_env *env = nullptr;
188 ani_status status = ANI_ERROR;
189 if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) {
190 TAG_LOGE(AAFwkTag::FREE_INSTALL, "Failed to getEnv, status: %{public}d", status);
191 }
192 ani_object aniObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK);
193 AppExecFwk::AsyncCallback(env, callback, aniObject, abilityResult);
194 env->GlobalReference_Delete(callback);
195 }
196
AddEtsObserverObject(ani_env * env,const std::string & bundleName,const std::string & abilityName,const std::string & startTime,ani_object callback,bool isAbilityResult)197 void EtsFreeInstallObserver::AddEtsObserverObject(ani_env *env, const std::string &bundleName,
198 const std::string &abilityName, const std::string &startTime, ani_object callback, bool isAbilityResult)
199 {
200 TAG_LOGD(AAFwkTag::FREE_INSTALL, "AddEtsObserverObject");
201 {
202 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
203 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end(); ++it) {
204 if (it->bundleName == bundleName && it->abilityName == abilityName && it->startTime == startTime) {
205 TAG_LOGW(AAFwkTag::FREE_INSTALL, "The EtsFreeInstallObserverObject has been added");
206 return;
207 }
208 }
209 }
210 StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
211 EtsFreeInstallObserverObject object;
212 object.bundleName = bundleName;
213 object.abilityName = abilityName;
214 object.startTime = startTime;
215 object.isAbilityResult = isAbilityResult;
216 AddEtsObserverCommon(env, object, callback);
217 }
218
AddEtsObserverObject(ani_env * env,const std::string & startTime,const std::string & url,ani_object callback,bool isAbilityResult)219 void EtsFreeInstallObserver::AddEtsObserverObject(
220 ani_env *env, const std::string &startTime, const std::string &url, ani_object callback, bool isAbilityResult)
221 {
222 TAG_LOGD(AAFwkTag::FREE_INSTALL, "AddEtsObserverObject");
223 {
224 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
225 for (auto it = etsObserverObjectList_.begin(); it != etsObserverObjectList_.end(); ++it) {
226 if (it->startTime == startTime && it->url == url) {
227 TAG_LOGW(AAFwkTag::FREE_INSTALL, "add etsObject");
228 return;
229 }
230 }
231 }
232 StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
233 EtsFreeInstallObserverObject object;
234 object.url = url;
235 object.startTime = startTime;
236 object.isAbilityResult = isAbilityResult;
237 AddEtsObserverCommon(env, object, callback);
238 }
239
AddEtsObserverCommon(ani_env * env,EtsFreeInstallObserverObject & object,ani_object callback)240 void EtsFreeInstallObserver::AddEtsObserverCommon(
241 ani_env *env, EtsFreeInstallObserverObject &object, ani_object callback)
242 {
243 TAG_LOGD(AAFwkTag::FREE_INSTALL, "AddEtsObserverCommon");
244 std::unique_lock<std::mutex> lock(etsObserverObjectListLock_);
245 ani_ref global = nullptr;
246 ani_status status = ANI_ERROR;
247 if ((status = env->GlobalReference_Create(callback, &global)) != ANI_OK) {
248 TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status);
249 return;
250 }
251 object.callback = reinterpret_cast<ani_object>(global);
252 etsObserverObjectList_.emplace_back(object);
253 }
254 } // namespace AbilityRuntime
255 } // namespace OHOS