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