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 "app_fwk_update_service.h"
17
18 #include "appspawn.h"
19 #include "bundle_mgr_client.h"
20 #include "bundle_mgr_interface.h"
21 #include "bundle_mgr_proxy.h"
22 #include "common_event_manager.h"
23 #include "common_event_support.h"
24 #include "event_handler.h"
25 #include "ipc_skeleton.h"
26 #include "iremote_object.h"
27 #include "iservice_registry.h"
28 #include "nweb_log.h"
29 #include "parameter.h"
30 #include "parameters.h"
31 #include "system_ability_definition.h"
32 #include "sysversion.h"
33
34 namespace OHOS::NWeb {
35
36 namespace {
37 const std::string ARK_WEB_BUNDLE_NAME = "com.ohos.nweb";
38 const int RETRY_COUNT = 2;
39 const int FOUNDATION_UID = 5523;
40 REGISTER_SYSTEM_ABILITY_BY_ID(AppFwkUpdateService, SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID, false);
41
42 constexpr int32_t TASK_DELAY_TIME = 60000; // 1min = 1*60*1000
43 const std::string TASK_ID = "unload";
44 const std::string PERSIST_ARKWEBCORE_PACKAGE_NAME = "persist.arkwebcore.package_name";
45 const std::set<std::string> ARK_WEB_DEFAULT_BUNDLE_NAME_SET = { "com.ohos.nweb", "com.ohos.arkwebcore" };
46 const std::string NWEB_HAP_PATH_MODULE_UPDATE = "/module_update/ArkWebCore/app/com.ohos.nweb/NWeb.hap";
47 } // namespace
48
PackageChangedReceiver(const EventFwk::CommonEventSubscribeInfo & subscribeInfo,const PackageCommonEventCallback & callback)49 PackageChangedReceiver::PackageChangedReceiver(
50 const EventFwk::CommonEventSubscribeInfo& subscribeInfo, const PackageCommonEventCallback& callback)
51 : EventFwk::CommonEventSubscriber(subscribeInfo), callback_(callback)
52 {}
53
OnReceiveEvent(const EventFwk::CommonEventData & data)54 void PackageChangedReceiver::OnReceiveEvent(const EventFwk::CommonEventData& data)
55 {
56 std::string action = data.GetWant().GetAction();
57 if (action.empty()) {
58 WVLOG_I("action is empty");
59 return;
60 }
61
62 std::string bundleName = data.GetWant().GetBundle();
63 if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
64 WVLOG_I("Bundle name is not nweb.");
65 return;
66 }
67
68 WVLOG_I("packagechangeReceiver OnReceiveEvent, ret = %{public}s.", action.c_str());
69 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED) {
70 std::string hapPath;
71 OHOS::AppExecFwk::BundleInfo bundleInfo;
72 OHOS::AppExecFwk::BundleMgrClient client;
73
74 bool result = client.GetBundleInfo(bundleName, OHOS::AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo,
75 AppExecFwk::Constants::ALL_USERID);
76 if (result) {
77 if (bundleInfo.hapModuleInfos.size() > 0) {
78 hapPath = bundleInfo.hapModuleInfos[0].hapPath;
79 WVLOG_I("PackagechangeReceiver hapPath is %{public}s.", hapPath.c_str());
80 }
81 callback_.OnPackageChangedEvent(bundleName, hapPath);
82 } else {
83 WVLOG_I("Failed to get bundleInfo.");
84 }
85 }
86 }
87
AppFwkUpdateService(int32_t saId,bool runOnCreate)88 AppFwkUpdateService::AppFwkUpdateService(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
89
~AppFwkUpdateService()90 AppFwkUpdateService::~AppFwkUpdateService() {}
91
NotifyFWKAfterBmsStart()92 ErrCode AppFwkUpdateService::NotifyFWKAfterBmsStart()
93 {
94 const std::string bundleName = OHOS::system::GetParameter(PERSIST_ARKWEBCORE_PACKAGE_NAME, "");
95 if (bundleName.empty()) {
96 WVLOG_E("NotifyFWKAfterBmsStart bundleName is empty");
97 return ERR_INVALID_VALUE;
98 }
99 WVLOG_I("NotifyFWKAfterBmsStart bundleName: %{public}s", bundleName.c_str());
100 int ret = SendAppSpawnMessage(bundleName, MSG_LOAD_WEBLIB_IN_APPSPAWN);
101 if (ret != 0) {
102 return ERR_INVALID_VALUE;
103 }
104 return ERR_OK;
105 }
106
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath,int32_t & isSuccess)107 ErrCode AppFwkUpdateService::VerifyPackageInstall(
108 const std::string& bundleName, const std::string& hapPath, int32_t& isSuccess)
109 {
110 if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
111 return ERR_INVALID_VALUE;
112 }
113 int ret = 0;
114 isSuccess = 0;
115 if (OHOS::system::GetParameter("persist.arkwebcore.install_path", "") == hapPath) {
116 WVLOG_I("OnPackageChangedEvent install path not changed.");
117 return ERR_OK;
118 }
119
120 ret = SetWebInstallPath(hapPath);
121 if (ret != 1) {
122 isSuccess = -1;
123 WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
124 return ERR_INVALID_VALUE;
125 }
126
127 ret = SetWebCorePackageName(bundleName);
128 if (ret != 1) {
129 isSuccess = -1;
130 WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
131 return ERR_INVALID_VALUE;
132 }
133
134 ret = SendAppSpawnMessage(bundleName, MSG_UPDATE_MOUNT_POINTS);
135 if (ret != 0) {
136 isSuccess = -1;
137 WVLOG_I("SendAppSpawnMessage happend error: %{public}d", isSuccess);
138 return ERR_INVALID_VALUE;
139 }
140 return ERR_OK;
141 }
142
OnStart(const SystemAbilityOnDemandReason & startReason)143 void AppFwkUpdateService::OnStart(const SystemAbilityOnDemandReason& startReason)
144 {
145 WVLOG_I("Servie on start.");
146 if (registerToService_) {
147 WVLOG_I("App fwk update service is running.");
148 }
149 if (!Init(startReason)) {
150 return;
151 }
152 }
153
Init(const SystemAbilityOnDemandReason & startReason)154 bool AppFwkUpdateService::Init(const SystemAbilityOnDemandReason& startReason)
155 {
156 std::string reasonName = startReason.GetName();
157 std::string reasonValue = startReason.GetValue();
158 WVLOG_I("AppFwkUpdateService reasonName: %{public}s", reasonName.c_str());
159 PostDelayUnloadTask();
160 bool ret = Publish(this);
161 if (!ret) {
162 WVLOG_I("Service publish failed.");
163 return false;
164 }
165 AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
166
167 std::string bundleName = "";
168 if (startReason.HasExtraData()) {
169 auto reasonMap = startReason.GetExtraData().GetWant();
170 for (auto i = reasonMap.begin(); i != reasonMap.end(); ++i) {
171 std::string key = std::string(i->first.data());
172 std::string value = std::string(i->second.data());
173 if (key == "bundleName") {
174 bundleName = value;
175 WVLOG_I("AppFwkUpdateService bundleName: %{public}s", bundleName.c_str());
176 break;
177 }
178 }
179 }
180 if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
181 WVLOG_I("Bundle name is not nweb.");
182 return false;
183 }
184 registerToService_ = true;
185 WVLOG_I("Service init success.");
186 return true;
187 }
188
SendAppSpawnMessage(const std::string & bundleName,AppSpawnMsgType msgType)189 int AppFwkUpdateService::SendAppSpawnMessage(const std::string& bundleName, AppSpawnMsgType msgType)
190 {
191 WVLOG_I("Send appspawn message start,uid = %{public}d.", getuid());
192 int ret = 0;
193 int retryCount = 0;
194 AppSpawnClientHandle clientHandle = nullptr;
195 AppSpawnReqMsgHandle reqHandle = 0;
196 do {
197 ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
198 if (ret != 0) {
199 WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
200 continue;
201 }
202 ret = AppSpawnReqMsgCreate(msgType, bundleName.c_str(), &reqHandle);
203 if (ret != 0) {
204 WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
205 continue;
206 }
207 AppSpawnResult result = {};
208 ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
209 } while (++retryCount < RETRY_COUNT && ret != 0);
210 AppSpawnClientDestroy(clientHandle);
211 WVLOG_I("Send appspawn message success.");
212 return ret;
213 }
214
SendNWebSpawnMesage(const std::string & bundleName)215 int AppFwkUpdateService::SendNWebSpawnMesage(const std::string& bundleName)
216 {
217 WVLOG_I("Send nweb spawn messagestart,uid = %{public}d.", getuid());
218 int ret = 0;
219 int retryCount = 0;
220 AppSpawnClientHandle clientHandle = nullptr;
221 AppSpawnReqMsgHandle reqHandle = 0;
222 do {
223 ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &clientHandle);
224 if (ret != 0) {
225 WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
226 continue;
227 }
228 ret = AppSpawnReqMsgCreate(MSG_RESTART_SPAWNER, bundleName.c_str(), &reqHandle);
229 if (ret != 0) {
230 WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
231 continue;
232 }
233 AppSpawnResult result = {};
234 ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
235 } while (++retryCount < RETRY_COUNT && ret != 0);
236 AppSpawnClientDestroy(clientHandle);
237 WVLOG_I("SendNWebSpawnMesage res = %{public}d.", ret);
238 return ret;
239 }
240
SetWebInstallPath(const std::string & path)241 int AppFwkUpdateService::SetWebInstallPath(const std::string& path)
242 {
243 int res = OHOS::system::SetParameter("persist.arkwebcore.install_path", path);
244 WVLOG_I("SetWebInstallPath res = %{public}d.", res);
245 return res;
246 }
SetWebCorePackageName(const std::string & packageName)247 int AppFwkUpdateService::SetWebCorePackageName(const std::string& packageName)
248 {
249 int res = OHOS::system::SetParameter("persist.arkwebcore.package_name", packageName);
250 WVLOG_I("SetWebCorePackageName res = %{public}d.", res);
251 return res;
252 }
253
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)254 void AppFwkUpdateService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
255 {
256 WVLOG_I("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId);
257 if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
258 SubscribePackageChangedEvent();
259 return;
260 }
261 }
262
SubscribePackageChangedEvent()263 void AppFwkUpdateService::SubscribePackageChangedEvent()
264 {
265 EventFwk::MatchingSkills matchingSkills;
266 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
267 EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
268 PackageCommonEventCallback callback = { std::bind(
269 &AppFwkUpdateService::OnPackageChangedEvent, this, std::placeholders::_1, std::placeholders::_2) };
270 pkgSubscriber_ = std::make_shared<PackageChangedReceiver>(subscribeInfo, callback);
271 if (pkgSubscriber_ == nullptr) {
272 WVLOG_I("Create package changed subscriber failed");
273 return;
274 }
275 if (!EventFwk::CommonEventManager::SubscribeCommonEvent(pkgSubscriber_)) {
276 WVLOG_I("Subscribe package changed event fail");
277 }
278 }
279
OnPackageChangedEvent(const std::string & bunldeName,const std::string & hapPath)280 void AppFwkUpdateService::OnPackageChangedEvent(const std::string& bunldeName, const std::string& hapPath)
281 {
282 SendNWebSpawnMesage(bunldeName);
283 }
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)284 void AppFwkUpdateService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
285 {
286 if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
287 WVLOG_I("systemAbilityId is not COMMON_EVENT_SERVICE_ID");
288 return;
289 }
290 if (pkgSubscriber_ == nullptr) {
291 WVLOG_I("OnRemoveSystemAbility subscribeer is nullptr");
292 return;
293 }
294 bool result = OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(pkgSubscriber_);
295 WVLOG_I("UnSubscribeCommonEvent subscriber result = %{public}d", result);
296 }
297
OnStop()298 void AppFwkUpdateService::OnStop()
299 {
300 WVLOG_I("Ready to stop service.");
301 registerToService_ = false;
302 }
303
PostDelayUnloadTask()304 void AppFwkUpdateService::PostDelayUnloadTask()
305 {
306 if (runner_ == nullptr) {
307 runner_ = AppExecFwk::EventRunner::Create("unload");
308 }
309 if (unloadHandler_ == nullptr) {
310 unloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
311 }
312 if (unloadHandler_ == nullptr) {
313 WVLOG_I("PostDelayUnloadTask invoke failed return.");
314 return;
315 }
316
317 auto task = [this]() {
318 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
319 if (samgrProxy == nullptr) {
320 WVLOG_I("Get samgrProxy failed.");
321 return;
322 }
323 int32_t ret = samgrProxy->UnloadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
324 if (ret != 0) {
325 WVLOG_I("Unload sa failed.");
326 return;
327 }
328 WVLOG_I("Do unload task done.");
329 };
330 unloadHandler_->RemoveTask(TASK_ID);
331 unloadHandler_->PostTask(task, TASK_ID, TASK_DELAY_TIME);
332 }
333 } // namespace OHOS::NWeb
334