• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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