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
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath,int32_t & isSuccess)92 ErrCode AppFwkUpdateService::VerifyPackageInstall(
93 const std::string& bundleName, const std::string& hapPath, int32_t& isSuccess)
94 {
95 if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
96 return ERR_INVALID_VALUE;
97 }
98 int ret = 0;
99 isSuccess = 0;
100 if (OHOS::system::GetParameter("persist.arkwebcore.install_path", "") == hapPath) {
101 WVLOG_I("OnPackageChangedEvent install path not changed.");
102 return ERR_OK;
103 }
104
105 ret = SetWebInstallPath(hapPath);
106 if (ret != 1) {
107 isSuccess = -1;
108 WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
109 return ERR_INVALID_VALUE;
110 }
111
112 ret = SetWebCorePackageName(bundleName);
113 if (ret != 1) {
114 isSuccess = -1;
115 WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
116 return ERR_INVALID_VALUE;
117 }
118
119 ret = SendAppSpawnMessage(bundleName);
120 if (ret != 0) {
121 isSuccess = -1;
122 WVLOG_I("SendAppSpawnMessage happend error: %{public}d", isSuccess);
123 return ERR_INVALID_VALUE;
124 }
125 return ERR_OK;
126 }
127
OnStart(const SystemAbilityOnDemandReason & startReason)128 void AppFwkUpdateService::OnStart(const SystemAbilityOnDemandReason& startReason)
129 {
130 WVLOG_I("Servie on start.");
131 if (registerToService_) {
132 WVLOG_I("App fwk update service is running.");
133 }
134 if (!Init(startReason)) {
135 return;
136 }
137 }
138
Init(const SystemAbilityOnDemandReason & startReason)139 bool AppFwkUpdateService::Init(const SystemAbilityOnDemandReason& startReason)
140 {
141 std::string reasonName = startReason.GetName();
142 std::string reasonValue = startReason.GetValue();
143 WVLOG_I("AppFwkUpdateService reasonName: %{public}s", reasonName.c_str());
144 PostDelayUnloadTask();
145 bool ret = Publish(this);
146 if (!ret) {
147 WVLOG_I("Service publish failed.");
148 return false;
149 }
150 AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
151
152 std::string bundleName = "";
153 if (startReason.HasExtraData()) {
154 auto reasonMap = startReason.GetExtraData().GetWant();
155 for (auto i = reasonMap.begin(); i != reasonMap.end(); ++i) {
156 std::string key = std::string(i->first.data());
157 std::string value = std::string(i->second.data());
158 if (key == "bundleName") {
159 bundleName = value;
160 WVLOG_I("AppFwkUpdateService bundleName: %{public}s", bundleName.c_str());
161 break;
162 }
163 }
164 }
165 if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
166 WVLOG_I("Bundle name is not nweb.");
167 return false;
168 }
169 registerToService_ = true;
170 WVLOG_I("Service init success.");
171 return true;
172 }
173
SendAppSpawnMessage(const std::string & bundleName)174 int AppFwkUpdateService::SendAppSpawnMessage(const std::string& bundleName)
175 {
176 WVLOG_I("Send appspawn message start,uid = %{public}d.", getuid());
177 int ret = 0;
178 int retryCount = 0;
179 AppSpawnClientHandle clientHandle = nullptr;
180 AppSpawnReqMsgHandle reqHandle = 0;
181 do {
182 ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
183 if (ret != 0) {
184 WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
185 continue;
186 }
187 ret = AppSpawnReqMsgCreate(MSG_UPDATE_MOUNT_POINTS, bundleName.c_str(), &reqHandle);
188 if (ret != 0) {
189 WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
190 continue;
191 }
192 AppSpawnResult result = {};
193 ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
194 } while (++retryCount < RETRY_COUNT && ret != 0);
195 AppSpawnClientDestroy(clientHandle);
196 WVLOG_I("Send appspawn message success.");
197 return ret;
198 }
199
SendNWebSpawnMesage(const std::string & bundleName)200 int AppFwkUpdateService::SendNWebSpawnMesage(const std::string& bundleName)
201 {
202 WVLOG_I("Send nweb spawn messagestart,uid = %{public}d.", getuid());
203 int ret = 0;
204 int retryCount = 0;
205 AppSpawnClientHandle clientHandle = nullptr;
206 AppSpawnReqMsgHandle reqHandle = 0;
207 do {
208 ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &clientHandle);
209 if (ret != 0) {
210 WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
211 continue;
212 }
213 ret = AppSpawnReqMsgCreate(MSG_RESTART_SPAWNER, bundleName.c_str(), &reqHandle);
214 if (ret != 0) {
215 WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
216 continue;
217 }
218 AppSpawnResult result = {};
219 ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
220 } while (++retryCount < RETRY_COUNT && ret != 0);
221 AppSpawnClientDestroy(clientHandle);
222 WVLOG_I("SendNWebSpawnMesage res = %{public}d.", ret);
223 return ret;
224 }
225
SetWebInstallPath(const std::string & path)226 int AppFwkUpdateService::SetWebInstallPath(const std::string& path)
227 {
228 int res = OHOS::system::SetParameter("persist.arkwebcore.install_path", path);
229 WVLOG_I("SetWebInstallPath res = %{public}d.", res);
230 return res;
231 }
SetWebCorePackageName(const std::string & packageName)232 int AppFwkUpdateService::SetWebCorePackageName(const std::string& packageName)
233 {
234 int res = OHOS::system::SetParameter("persist.arkwebcore.package_name", packageName);
235 WVLOG_I("SetWebCorePackageName res = %{public}d.", res);
236 return res;
237 }
238
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)239 void AppFwkUpdateService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
240 {
241 WVLOG_I("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId);
242 if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
243 SubscribePackageChangedEvent();
244 return;
245 }
246 }
247
SubscribePackageChangedEvent()248 void AppFwkUpdateService::SubscribePackageChangedEvent()
249 {
250 EventFwk::MatchingSkills matchingSkills;
251 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
252 EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
253 PackageCommonEventCallback callback = { std::bind(
254 &AppFwkUpdateService::OnPackageChangedEvent, this, std::placeholders::_1, std::placeholders::_2) };
255 pkgSubscriber_ = std::make_shared<PackageChangedReceiver>(subscribeInfo, callback);
256 if (pkgSubscriber_ == nullptr) {
257 WVLOG_I("Create package changed subscriber failed");
258 return;
259 }
260 if (!EventFwk::CommonEventManager::SubscribeCommonEvent(pkgSubscriber_)) {
261 WVLOG_I("Subscribe package changed event fail");
262 }
263 }
264
OnPackageChangedEvent(const std::string & bunldeName,const std::string & hapPath)265 void AppFwkUpdateService::OnPackageChangedEvent(const std::string& bunldeName, const std::string& hapPath)
266 {
267 SendNWebSpawnMesage(bunldeName);
268 }
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)269 void AppFwkUpdateService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
270 {
271 if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
272 WVLOG_I("systemAbilityId is not COMMON_EVENT_SERVICE_ID");
273 return;
274 }
275 if (pkgSubscriber_ == nullptr) {
276 WVLOG_I("OnRemoveSystemAbility subscribeer is nullptr");
277 return;
278 }
279 bool result = OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(pkgSubscriber_);
280 WVLOG_I("UnSubscribeCommonEvent subscriber result = %{public}d", result);
281 }
282
OnStop()283 void AppFwkUpdateService::OnStop()
284 {
285 WVLOG_I("Ready to stop service.");
286 registerToService_ = false;
287 }
288
PostDelayUnloadTask()289 void AppFwkUpdateService::PostDelayUnloadTask()
290 {
291 if (runner_ == nullptr) {
292 runner_ = AppExecFwk::EventRunner::Create("unload");
293 }
294 if (unloadHandler_ == nullptr) {
295 unloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
296 }
297 if (unloadHandler_ == nullptr) {
298 WVLOG_I("PostDelayUnloadTask invoke failed return.");
299 return;
300 }
301
302 auto task = [this]() {
303 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
304 if (samgrProxy == nullptr) {
305 WVLOG_I("Get samgrProxy failed.");
306 return;
307 }
308 int32_t ret = samgrProxy->UnloadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
309 if (ret != 0) {
310 WVLOG_I("Unload sa failed.");
311 return;
312 }
313 WVLOG_I("Do unload task done.");
314 };
315 unloadHandler_->RemoveTask(TASK_ID);
316 unloadHandler_->PostTask(task, TASK_ID, TASK_DELAY_TIME);
317 }
318 } // namespace OHOS::NWeb
319