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 "child_main_thread.h"
17
18 #include <unistd.h>
19
20 #include "bundle_mgr_helper.h"
21 #include "bundle_mgr_proxy.h"
22 #include "child_process_manager.h"
23 #include "constants.h"
24 #include "hilog_tag_wrapper.h"
25 #include "js_runtime.h"
26 #include "native_lib_util.h"
27 #include "sys_mgr_client.h"
28 #include "system_ability_definition.h"
29
30 namespace OHOS {
31 namespace AppExecFwk {
32 using namespace OHOS::AbilityBase::Constants;
33 using OHOS::AbilityRuntime::ChildProcessManager;
ChildMainThread()34 ChildMainThread::ChildMainThread()
35 {
36 processArgs_ = std::make_shared<ChildProcessArgs>();
37 }
38
~ChildMainThread()39 ChildMainThread::~ChildMainThread()
40 {
41 TAG_LOGD(AAFwkTag::APPKIT, "ChildMainThread deconstructor called");
42 }
43
Start(const std::map<std::string,int32_t> & fds)44 void ChildMainThread::Start(const std::map<std::string, int32_t> &fds)
45 {
46 TAG_LOGI(AAFwkTag::APPKIT, "ChildMainThread start");
47 ChildProcessInfo processInfo;
48 auto ret = GetChildProcessInfo(processInfo);
49 if (ret != ERR_OK) {
50 TAG_LOGE(AAFwkTag::APPKIT, "GetChildProcessInfo failed, ret:%{public}d", ret);
51 return;
52 }
53
54 sptr<ChildMainThread> thread = sptr<ChildMainThread>(new (std::nothrow) ChildMainThread());
55 if (thread == nullptr) {
56 TAG_LOGE(AAFwkTag::APPKIT, "New ChildMainThread failed");
57 return;
58 }
59 thread->SetFds(fds);
60 std::shared_ptr<EventRunner> runner = EventRunner::GetMainEventRunner();
61 if (runner == nullptr) {
62 TAG_LOGE(AAFwkTag::APPKIT, "runner is null");
63 return;
64 }
65 if (!thread->Init(runner, processInfo)) {
66 TAG_LOGE(AAFwkTag::APPKIT, "ChildMainThread Init failed");
67 return;
68 }
69 if (!thread->Attach()) {
70 TAG_LOGE(AAFwkTag::APPKIT, "ChildMainThread Attach failed");
71 return;
72 }
73
74 ret = runner->Run();
75 if (ret != ERR_OK) {
76 TAG_LOGE(AAFwkTag::APPKIT, "ChildMainThread runner->Run failed ret = %{public}d", ret);
77 }
78
79 TAG_LOGD(AAFwkTag::APPKIT, "ChildMainThread end");
80 }
81
GetChildProcessInfo(ChildProcessInfo & info)82 int32_t ChildMainThread::GetChildProcessInfo(ChildProcessInfo &info)
83 {
84 TAG_LOGD(AAFwkTag::APPKIT, "called");
85 auto object = OHOS::DelayedSingleton<SysMrgClient>::GetInstance()->GetSystemAbility(APP_MGR_SERVICE_ID);
86 if (object == nullptr) {
87 TAG_LOGE(AAFwkTag::APPKIT, "failed to get app manager service");
88 return ERR_INVALID_VALUE;
89 }
90 auto appMgr = iface_cast<IAppMgr>(object);
91 if (appMgr == nullptr) {
92 TAG_LOGE(AAFwkTag::APPKIT, "failed to iface_cast object to appMgr");
93 return ERR_INVALID_VALUE;
94 }
95 return appMgr->GetChildProcessInfoForSelf(info);
96 }
97
SetFds(const std::map<std::string,int32_t> & fds)98 void ChildMainThread::SetFds(const std::map<std::string, int32_t> &fds)
99 {
100 if (!processArgs_) {
101 TAG_LOGE(AAFwkTag::APPKIT, "processArgs_ is nullptr");
102 return;
103 }
104 processArgs_->fds = fds;
105 }
106
Init(const std::shared_ptr<EventRunner> & runner,const ChildProcessInfo & processInfo)107 bool ChildMainThread::Init(const std::shared_ptr<EventRunner> &runner, const ChildProcessInfo &processInfo)
108 {
109 TAG_LOGD(AAFwkTag::APPKIT, "called");
110 if (runner == nullptr) {
111 TAG_LOGE(AAFwkTag::APPKIT, "runner is null");
112 return false;
113 }
114 processInfo_ = std::make_shared<ChildProcessInfo>(processInfo);
115 processArgs_->entryParams = processInfo.entryParams;
116 mainHandler_ = std::make_shared<EventHandler>(runner);
117 BundleInfo bundleInfo;
118 if (!ChildProcessManager::GetInstance().GetBundleInfo(bundleInfo)) {
119 TAG_LOGE(AAFwkTag::APPKIT, "GetBundleInfo failed!.");
120 return false;
121 }
122 bundleInfo_ = std::make_shared<BundleInfo>(bundleInfo);
123 InitNativeLib(bundleInfo);
124 return true;
125 }
126
Attach()127 bool ChildMainThread::Attach()
128 {
129 TAG_LOGD(AAFwkTag::APPKIT, "called");
130 auto sysMrgClient = DelayedSingleton<AppExecFwk::SysMrgClient>::GetInstance();
131 if (sysMrgClient == nullptr) {
132 TAG_LOGE(AAFwkTag::APPKIT, "Failed to get SysMrgClient");
133 return false;
134 }
135 auto object = sysMrgClient->GetSystemAbility(APP_MGR_SERVICE_ID);
136 if (object == nullptr) {
137 TAG_LOGE(AAFwkTag::APPKIT, "GetAppMgr failed");
138 return false;
139 }
140 appMgr_ = iface_cast<IAppMgr>(object);
141 if (appMgr_ == nullptr) {
142 TAG_LOGE(AAFwkTag::APPKIT, "failed to iface_cast object to appMgr_");
143 return false;
144 }
145 appMgr_->AttachChildProcess(this);
146 return true;
147 }
148
ScheduleLoadChild()149 bool ChildMainThread::ScheduleLoadChild()
150 {
151 TAG_LOGI(AAFwkTag::APPKIT, "ScheduleLoadChild called.");
152 if (mainHandler_ == nullptr) {
153 TAG_LOGE(AAFwkTag::APPKIT, "mainHandler_ is null");
154 return false;
155 }
156 if (!processInfo_) {
157 TAG_LOGE(AAFwkTag::APPKIT, "processInfo is nullptr");
158 return false;
159 }
160 auto childProcessType = processInfo_->childProcessType;
161 wptr<ChildMainThread> weak = this;
162 auto task = [weak, childProcessType]() {
163 auto childMainThread = weak.promote();
164 if (childMainThread == nullptr) {
165 TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleLoadChild failed.");
166 return;
167 }
168 if (childProcessType == CHILD_PROCESS_TYPE_ARK) {
169 childMainThread->HandleLoadArkTs();
170 } else if (childProcessType == CHILD_PROCESS_TYPE_NATIVE_ARGS) {
171 childMainThread->HandleLoadNative();
172 } else {
173 childMainThread->HandleLoadJs();
174 }
175 };
176 if (!mainHandler_->PostTask(task, "ChildMainThread::HandleLoadJs")) {
177 TAG_LOGE(AAFwkTag::APPKIT, "ChildMainThread::ScheduleLoadChild PostTask task failed.");
178 return false;
179 }
180 return true;
181 }
182
HandleLoadJs()183 void ChildMainThread::HandleLoadJs()
184 {
185 TAG_LOGD(AAFwkTag::APPKIT, "called");
186 if (!processInfo_ || !bundleInfo_) {
187 TAG_LOGE(AAFwkTag::APPKIT, "processInfo or bundleInfo_ is null");
188 return;
189 }
190 ChildProcessManager &childProcessManager = ChildProcessManager::GetInstance();
191 HapModuleInfo hapModuleInfo;
192 BundleInfo bundleInfoCopy = *bundleInfo_;
193 if (!childProcessManager.GetEntryHapModuleInfo(bundleInfoCopy, hapModuleInfo)) {
194 TAG_LOGE(AAFwkTag::APPKIT, "GetEntryHapModuleInfo failed");
195 return;
196 }
197
198 runtime_ = childProcessManager.CreateRuntime(bundleInfoCopy, hapModuleInfo, true, processInfo_->jitEnabled);
199 if (!runtime_) {
200 TAG_LOGE(AAFwkTag::APPKIT, "Failed to create child process runtime");
201 return;
202 }
203 AbilityRuntime::Runtime::DebugOption debugOption;
204 childProcessManager.SetAppSpawnForkDebugOption(debugOption, processInfo_);
205 TAG_LOGD(AAFwkTag::APPKIT, "StartDebugMode, isStartWithDebug is %{public}d, processName is %{public}s, "
206 "isDebugApp is %{public}d, isStartWithNative is %{public}d", processInfo_->isStartWithDebug,
207 processInfo_->processName.c_str(), processInfo_->isDebugApp, processInfo_->isStartWithNative);
208 runtime_->StartDebugMode(debugOption);
209 std::string srcPath;
210 srcPath.append(hapModuleInfo.moduleName).append("/").append(processInfo_->srcEntry);
211 childProcessManager.LoadJsFile(srcPath, hapModuleInfo, runtime_);
212 ExitProcessSafely();
213 }
214
HandleLoadArkTs()215 void ChildMainThread::HandleLoadArkTs()
216 {
217 TAG_LOGD(AAFwkTag::APPKIT, "called");
218 if (!processInfo_ || !bundleInfo_) {
219 TAG_LOGE(AAFwkTag::APPKIT, "processInfo or bundleInfo_ is null");
220 return;
221 }
222 if (!processArgs_) {
223 TAG_LOGE(AAFwkTag::APPKIT, "processArgs_ is nullptr");
224 return;
225 }
226 auto &srcEntry = processInfo_->srcEntry;
227 ChildProcessManager &childProcessManager = ChildProcessManager::GetInstance();
228 std::string moduleName = childProcessManager.GetModuleNameFromSrcEntry(srcEntry);
229 if (moduleName.empty()) {
230 TAG_LOGE(AAFwkTag::APPKIT, "Can't find module name from srcEntry, srcEntry is %{private}s", srcEntry.c_str());
231 return;
232 }
233 HapModuleInfo hapModuleInfo;
234 if (!childProcessManager.GetHapModuleInfo(*bundleInfo_, moduleName, hapModuleInfo)) {
235 TAG_LOGE(AAFwkTag::APPKIT, "GetHapModuleInfo failed, can't find module:%{public}s", moduleName.c_str());
236 return;
237 }
238
239 runtime_ = childProcessManager.CreateRuntime(*bundleInfo_, hapModuleInfo, true, processInfo_->jitEnabled);
240 if (!runtime_) {
241 TAG_LOGE(AAFwkTag::APPKIT, "Failed to create child process runtime");
242 return;
243 }
244 AbilityRuntime::Runtime::DebugOption debugOption;
245 childProcessManager.SetAppSpawnForkDebugOption(debugOption, processInfo_);
246 TAG_LOGD(AAFwkTag::APPKIT, "StartDebugMode, isStartWithDebug is %{public}d, processName is %{public}s, "
247 "isDebugApp is %{public}d, isStartWithNative is %{public}d", processInfo_->isStartWithDebug,
248 processInfo_->processName.c_str(), processInfo_->isDebugApp, processInfo_->isStartWithNative);
249 runtime_->StartDebugMode(debugOption);
250
251 childProcessManager.LoadJsFile(srcEntry, hapModuleInfo, runtime_, processArgs_);
252 }
253
HandleLoadNative()254 void ChildMainThread::HandleLoadNative()
255 {
256 TAG_LOGD(AAFwkTag::APPKIT, "HandleLoadNative called.");
257 if (!processInfo_) {
258 TAG_LOGE(AAFwkTag::APPKIT, "processInfo_ is null.");
259 return;
260 }
261 if (!processArgs_) {
262 TAG_LOGE(AAFwkTag::APPKIT, "processArgs_ is nullptr.");
263 return;
264 }
265 ChildProcessManager &childProcessMgr = ChildProcessManager::GetInstance();
266 childProcessMgr.LoadNativeLibWithArgs(nativeLibModuleName_, processInfo_->srcEntry, processInfo_->entryFunc,
267 processArgs_);
268 TAG_LOGD(AAFwkTag::APPKIT, "HandleLoadNative end.");
269 ExitProcessSafely();
270 }
271
InitNativeLib(const BundleInfo & bundleInfo)272 void ChildMainThread::InitNativeLib(const BundleInfo &bundleInfo)
273 {
274 HspList hspList;
275 ErrCode ret = DelayedSingleton<BundleMgrHelper>::GetInstance()->GetBaseSharedBundleInfos(bundleInfo.name, hspList,
276 AppExecFwk::GetDependentBundleInfoFlag::GET_ALL_DEPENDENT_BUNDLE_INFO);
277 if (ret != ERR_OK) {
278 TAG_LOGE(AAFwkTag::APPKIT, "Get base shared bundle infos failed: %{public}d", ret);
279 }
280
281 AppLibPathMap appLibPaths {};
282 GetNativeLibPath(bundleInfo, hspList, appLibPaths);
283 bool isSystemApp = bundleInfo.applicationInfo.isSystemApp;
284 TAG_LOGD(AAFwkTag::APPKIT, "the application isSystemApp: %{public}d", isSystemApp);
285
286 if (processInfo_->childProcessType != CHILD_PROCESS_TYPE_NATIVE &&
287 processInfo_->childProcessType != CHILD_PROCESS_TYPE_NATIVE_ARGS) {
288 AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp);
289 } else {
290 UpdateNativeChildLibModuleName(appLibPaths, isSystemApp);
291 }
292 }
293
ExitProcessSafely()294 void ChildMainThread::ExitProcessSafely()
295 {
296 if (appMgr_ == nullptr) {
297 TAG_LOGE(AAFwkTag::APPKIT, "appMgr_ is null, use exit(0) instead");
298 exit(0);
299 return;
300 }
301 appMgr_->ExitChildProcessSafely();
302 }
303
ScheduleExitProcessSafely()304 bool ChildMainThread::ScheduleExitProcessSafely()
305 {
306 TAG_LOGD(AAFwkTag::APPKIT, "ScheduleExitProcessSafely");
307 if (mainHandler_ == nullptr) {
308 TAG_LOGE(AAFwkTag::APPKIT, "mainHandler_ is null");
309 return false;
310 }
311 wptr<ChildMainThread> weak = this;
312 auto task = [weak]() {
313 auto childMainThread = weak.promote();
314 if (childMainThread == nullptr) {
315 TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleExitProcessSafely failed");
316 return;
317 }
318 childMainThread->HandleExitProcessSafely();
319 };
320 if (!mainHandler_->PostTask(task, "ChildMainThread::HandleExitProcessSafely")) {
321 TAG_LOGE(AAFwkTag::APPKIT, "ScheduleExitProcessSafely PostTask task failed");
322 return false;
323 }
324 return true;
325 }
326
HandleExitProcessSafely()327 void ChildMainThread::HandleExitProcessSafely()
328 {
329 TAG_LOGD(AAFwkTag::APPKIT, "called");
330 std::shared_ptr<EventRunner> runner = mainHandler_->GetEventRunner();
331 if (runner == nullptr) {
332 TAG_LOGE(AAFwkTag::APPKIT, "HandleExitProcessSafely get runner error");
333 return;
334 }
335 int ret = runner->Stop();
336 if (ret != ERR_OK) {
337 TAG_LOGE(AAFwkTag::APPKIT, "HandleExitProcessSafely failed. runner->Run failed ret = %{public}d", ret);
338 }
339 }
340
ScheduleRunNativeProc(const sptr<IRemoteObject> & mainProcessCb)341 bool ChildMainThread::ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb)
342 {
343 TAG_LOGD(AAFwkTag::APPKIT, "ScheduleRunNativeProc");
344 if (mainProcessCb == nullptr) {
345 TAG_LOGE(AAFwkTag::APPKIT, "Main process callback is null");
346 return false;
347 }
348
349 if (mainHandler_ == nullptr) {
350 TAG_LOGE(AAFwkTag::APPKIT, "mainHandler_ is null");
351 return false;
352 }
353
354 auto task = [weak = wptr<ChildMainThread>(this), callback = sptr<IRemoteObject>(mainProcessCb)]() {
355 auto childMainThread = weak.promote();
356 if (childMainThread == nullptr) {
357 TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleRunNativeProc failed");
358 return;
359 }
360 childMainThread->HandleRunNativeProc(callback);
361 };
362 if (!mainHandler_->PostTask(task, "ChildMainThread::HandleRunNativeProc")) {
363 TAG_LOGE(AAFwkTag::APPKIT, "HandleRunNativeProc PostTask task failed");
364 return false;
365 }
366 return true;
367 }
368
HandleRunNativeProc(const sptr<IRemoteObject> & mainProcessCb)369 void ChildMainThread::HandleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb)
370 {
371 TAG_LOGD(AAFwkTag::APPKIT, "called");
372 if (!processInfo_) {
373 TAG_LOGE(AAFwkTag::APPKIT, "processInfo is null");
374 return;
375 }
376
377 ChildProcessManager &childProcessMgr = ChildProcessManager::GetInstance();
378 childProcessMgr.LoadNativeLib(nativeLibModuleName_, processInfo_->srcEntry, mainProcessCb);
379 ExitProcessSafely();
380 }
381
UpdateNativeChildLibModuleName(const AppLibPathMap & appLibPaths,bool isSystemApp)382 void ChildMainThread::UpdateNativeChildLibModuleName(const AppLibPathMap &appLibPaths, bool isSystemApp)
383 {
384 nativeLibModuleName_.clear();
385 NativeModuleManager *nativeModuleMgr = NativeModuleManager::GetInstance();
386 if (nativeModuleMgr == nullptr) {
387 TAG_LOGE(AAFwkTag::APPKIT, "Get native module manager for native child failed");
388 return;
389 }
390
391 std::string nativeLibPath;
392 for (const auto &libPathPair : appLibPaths) {
393 for (const auto &libDir : libPathPair.second) {
394 nativeLibPath = libDir;
395 if (!nativeLibPath.empty() && nativeLibPath.back() != '/') {
396 nativeLibPath += '/';
397 }
398 nativeLibPath += processInfo_->srcEntry;
399 if (access(nativeLibPath.c_str(), F_OK) == 0) {
400 nativeLibModuleName_ = libPathPair.first;
401 nativeModuleMgr->SetAppLibPath(libPathPair.first, libPathPair.second, isSystemApp);
402 TAG_LOGI(AAFwkTag::APPKIT, "Find native lib in app module: %{public}s", libPathPair.first.c_str());
403 return;
404 }
405 }
406 }
407
408 TAG_LOGE(AAFwkTag::APPKIT, "Can not find native lib(%{private}s) in any app module",
409 processInfo_->srcEntry.c_str());
410 }
411
GetNativeLibPath(const BundleInfo & bundleInfo,const HspList & hspList,AppLibPathMap & appLibPaths)412 void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList,
413 AppLibPathMap &appLibPaths)
414 {
415 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
416 if (!nativeLibraryPath.empty()) {
417 if (nativeLibraryPath.back() == '/') {
418 nativeLibraryPath.pop_back();
419 }
420 std::string libPath = LOCAL_CODE_PATH;
421 libPath += (libPath.back() == '/') ? nativeLibraryPath : "/" + nativeLibraryPath;
422 TAG_LOGI(AAFwkTag::APPKIT, "napi lib path = %{private}s", libPath.c_str());
423 appLibPaths["default"].emplace_back(libPath);
424 }
425
426 for (auto &hapInfo : bundleInfo.hapModuleInfos) {
427 TAG_LOGD(AAFwkTag::APPKIT,
428 "moduleName: %{public}s, isLibIsolated: %{public}d, compressNativeLibs: %{public}d",
429 hapInfo.moduleName.c_str(), hapInfo.isLibIsolated, hapInfo.compressNativeLibs);
430 GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH));
431 }
432
433 for (auto &hspInfo : hspList) {
434 TAG_LOGD(AAFwkTag::APPKIT, "bundle:%s, module:%s, nativeLibraryPath:%s", hspInfo.bundleName.c_str(),
435 hspInfo.moduleName.c_str(), hspInfo.nativeLibraryPath.c_str());
436 GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u);
437 }
438 }
439 } // namespace AppExecFwk
440 } // namespace OHOS
441