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