1 /*
2 * Copyright (c) 2023 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 "bundle_mgr_proxy.h"
19 #include "child_process_manager.h"
20 #include "constants.h"
21 #include "hilog_wrapper.h"
22 #include "js_runtime.h"
23 #include "sys_mgr_client.h"
24 #include "system_ability_definition.h"
25
26 namespace OHOS {
27 namespace AppExecFwk {
28 using namespace OHOS::AbilityBase::Constants;
29 using OHOS::AbilityRuntime::ChildProcessManager;
ChildMainThread()30 ChildMainThread::ChildMainThread()
31 {
32 HILOG_DEBUG("ChildMainThread constructor called");
33 }
34
~ChildMainThread()35 ChildMainThread::~ChildMainThread()
36 {
37 HILOG_DEBUG("ChildMainThread deconstructor called");
38 }
39
Start(const ChildProcessInfo & processInfo)40 void ChildMainThread::Start(const ChildProcessInfo &processInfo)
41 {
42 HILOG_INFO("ChildMainThread start.");
43 sptr<ChildMainThread> thread = sptr<ChildMainThread>(new (std::nothrow) ChildMainThread());
44 if (thread == nullptr) {
45 HILOG_ERROR("New ChildMainThread failed.");
46 return;
47 }
48 std::shared_ptr<EventRunner> runner = EventRunner::GetMainEventRunner();
49 if (runner == nullptr) {
50 HILOG_ERROR("runner is null.");
51 return;
52 }
53 if (!thread->Init(runner, processInfo)) {
54 HILOG_ERROR("ChildMainThread Init failed.");
55 return;
56 }
57 if (!thread->Attach()) {
58 HILOG_ERROR("ChildMainThread Attach failed.");
59 return;
60 }
61
62 auto ret = runner->Run();
63 if (ret != ERR_OK) {
64 HILOG_ERROR("ChildMainThread runner->Run failed ret = %{public}d", ret);
65 }
66
67 HILOG_DEBUG("ChildMainThread end.");
68 }
69
Init(const std::shared_ptr<EventRunner> & runner,const ChildProcessInfo & processInfo)70 bool ChildMainThread::Init(const std::shared_ptr<EventRunner> &runner, const ChildProcessInfo &processInfo)
71 {
72 HILOG_DEBUG("ChildMainThread:Init called.");
73 if (runner == nullptr) {
74 HILOG_ERROR("runner is null.");
75 return false;
76 }
77 processInfo_ = std::make_shared<ChildProcessInfo>(processInfo);
78 mainHandler_ = std::make_shared<EventHandler>(runner);
79 BundleInfo bundleInfo;
80 if (!ChildProcessManager::GetInstance().GetBundleInfo(bundleInfo)) {
81 HILOG_ERROR("GetBundleInfo failed!.");
82 return false;
83 }
84 bundleInfo_ = std::make_shared<BundleInfo>(bundleInfo);
85 InitNativeLib(bundleInfo);
86 return true;
87 }
88
Attach()89 bool ChildMainThread::Attach()
90 {
91 HILOG_DEBUG("ChildMainThread::Attach called.");
92 auto sysMrgClient = DelayedSingleton<AppExecFwk::SysMrgClient>::GetInstance();
93 if (sysMrgClient == nullptr) {
94 HILOG_ERROR("Failed to get SysMrgClient.");
95 return false;
96 }
97 auto object = sysMrgClient->GetSystemAbility(APP_MGR_SERVICE_ID);
98 if (object == nullptr) {
99 HILOG_ERROR("GetAppMgr failed.");
100 return false;
101 }
102 appMgr_ = iface_cast<IAppMgr>(object);
103 if (appMgr_ == nullptr) {
104 HILOG_ERROR("failed to iface_cast object to appMgr_");
105 return false;
106 }
107 appMgr_->AttachChildProcess(this);
108 return true;
109 }
110
ScheduleLoadJs()111 bool ChildMainThread::ScheduleLoadJs()
112 {
113 HILOG_INFO("ScheduleLoadJs called.");
114 if (mainHandler_ == nullptr) {
115 HILOG_ERROR("mainHandler_ is null");
116 return false;
117 }
118 wptr<ChildMainThread> weak = this;
119 auto task = [weak]() {
120 auto childMainThread = weak.promote();
121 if (childMainThread == nullptr) {
122 HILOG_ERROR("childMainThread is nullptr, ScheduleLoadJs failed.");
123 return;
124 }
125 childMainThread->HandleLoadJs();
126 };
127 if (!mainHandler_->PostTask(task, "ChildMainThread::HandleLoadJs")) {
128 HILOG_ERROR("ChildMainThread::ScheduleLoadJs PostTask task failed.");
129 return false;
130 }
131 return true;
132 }
133
HandleLoadJs()134 void ChildMainThread::HandleLoadJs()
135 {
136 HILOG_DEBUG("called.");
137 if (!processInfo_ || !bundleInfo_) {
138 HILOG_ERROR("processInfo or bundleInfo_ is null.");
139 return;
140 }
141 ChildProcessManager &childProcessManager = ChildProcessManager::GetInstance();
142 HapModuleInfo hapModuleInfo;
143 BundleInfo bundleInfoCopy = *bundleInfo_;
144 if (!childProcessManager.GetHapModuleInfo(bundleInfoCopy, hapModuleInfo)) {
145 HILOG_ERROR("GetHapModuleInfo failed.");
146 return;
147 }
148
149 runtime_ = childProcessManager.CreateRuntime(bundleInfoCopy, hapModuleInfo, true);
150 if (!runtime_) {
151 HILOG_ERROR("Failed to create child process runtime");
152 return;
153 }
154 childProcessManager.LoadJsFile(processInfo_->srcEntry, hapModuleInfo, runtime_);
155 HILOG_DEBUG("ChildMainThread::HandleLoadJs end.");
156 ExitProcessSafely();
157 }
158
InitNativeLib(const BundleInfo & bundleInfo)159 void ChildMainThread::InitNativeLib(const BundleInfo &bundleInfo)
160 {
161 AppLibPathMap appLibPaths {};
162 GetNativeLibPath(bundleInfo, appLibPaths);
163 bool isSystemApp = bundleInfo.applicationInfo.isSystemApp;
164 HILOG_DEBUG("the application isSystemApp: %{public}d", isSystemApp);
165 AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp);
166 }
167
ExitProcessSafely()168 void ChildMainThread::ExitProcessSafely()
169 {
170 if (appMgr_ == nullptr) {
171 HILOG_ERROR("appMgr_ is null, use exit(0) instead.");
172 exit(0);
173 return;
174 }
175 appMgr_->ExitChildProcessSafely();
176 }
177
ScheduleExitProcessSafely()178 bool ChildMainThread::ScheduleExitProcessSafely()
179 {
180 HILOG_DEBUG("ScheduleExitProcessSafely");
181 if (mainHandler_ == nullptr) {
182 HILOG_ERROR("mainHandler_ is null");
183 return false;
184 }
185 wptr<ChildMainThread> weak = this;
186 auto task = [weak]() {
187 auto childMainThread = weak.promote();
188 if (childMainThread == nullptr) {
189 HILOG_ERROR("childMainThread is nullptr, ScheduleExitProcessSafely failed.");
190 return;
191 }
192 childMainThread->HandleExitProcessSafely();
193 };
194 if (!mainHandler_->PostTask(task, "ChildMainThread::HandleExitProcessSafely")) {
195 HILOG_ERROR("ScheduleExitProcessSafely PostTask task failed.");
196 return false;
197 }
198 return true;
199 }
200
HandleExitProcessSafely()201 void ChildMainThread::HandleExitProcessSafely()
202 {
203 HILOG_DEBUG("HandleExitProcessSafely called start.");
204 std::shared_ptr<EventRunner> runner = mainHandler_->GetEventRunner();
205 if (runner == nullptr) {
206 HILOG_ERROR("HandleExitProcessSafely get runner error.");
207 return;
208 }
209 int ret = runner->Stop();
210 if (ret != ERR_OK) {
211 HILOG_ERROR("HandleExitProcessSafely failed. runner->Run failed ret = %{public}d", ret);
212 }
213 }
214
GetNativeLibPath(const BundleInfo & bundleInfo,AppLibPathMap & appLibPaths)215 void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathMap &appLibPaths)
216 {
217 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
218 if (!nativeLibraryPath.empty()) {
219 if (nativeLibraryPath.back() == '/') {
220 nativeLibraryPath.pop_back();
221 }
222 std::string libPath = LOCAL_CODE_PATH;
223 libPath += (libPath.back() == '/') ? nativeLibraryPath : "/" + nativeLibraryPath;
224 HILOG_INFO("napi lib path = %{private}s", libPath.c_str());
225 appLibPaths["default"].emplace_back(libPath);
226 }
227
228 for (auto &hapInfo : bundleInfo.hapModuleInfos) {
229 HILOG_DEBUG("moduleName: %{public}s, isLibIsolated: %{public}d, compressNativeLibs: %{public}d.",
230 hapInfo.moduleName.c_str(), hapInfo.isLibIsolated, hapInfo.compressNativeLibs);
231 GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH));
232 }
233 }
234
GetHapSoPath(const HapModuleInfo & hapInfo,AppLibPathMap & appLibPaths,bool isPreInstallApp)235 void ChildMainThread::GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp)
236 {
237 if (hapInfo.nativeLibraryPath.empty()) {
238 HILOG_DEBUG("Lib path of %{public}s is empty, lib isn't isolated or compressed.", hapInfo.moduleName.c_str());
239 return;
240 }
241
242 std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName;
243 std::string libPath = LOCAL_CODE_PATH;
244 if (!hapInfo.compressNativeLibs) {
245 HILOG_DEBUG("Lib of %{public}s will not be extracted from hap.", hapInfo.moduleName.c_str());
246 libPath = GetLibPath(hapInfo.hapPath, isPreInstallApp);
247 }
248
249 libPath += (libPath.back() == '/') ? hapInfo.nativeLibraryPath : "/" + hapInfo.nativeLibraryPath;
250 HILOG_INFO("appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str());
251 appLibPaths[appLibPathKey].emplace_back(libPath);
252 }
253
GetLibPath(const std::string & hapPath,bool isPreInstallApp)254 std::string ChildMainThread::GetLibPath(const std::string &hapPath, bool isPreInstallApp)
255 {
256 std::string libPath = LOCAL_CODE_PATH;
257 if (isPreInstallApp) {
258 auto pos = hapPath.rfind("/");
259 if (pos != std::string::npos) {
260 libPath = hapPath.substr(0, pos);
261 }
262 }
263 return libPath;
264 }
265 } // namespace AppExecFwk
266 } // namespace OHOS
267