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