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