1 /*
2 * Copyright (c) 2021-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 "app_spawn_client.h"
17
18 #include "hitrace_meter.h"
19 #include "hilog_wrapper.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 const int32_t CONNECT_RETRY_DELAY = 200 * 1000; // 200ms
25 const int32_t CONNECT_RETRY_MAX_TIMES = 2;
26 const size_t SOCK_MAX_SEND_BUFFER = 5 * 1024; // 5KB
27 } // namespace
28
AppSpawnClient(bool isNWebSpawn)29 AppSpawnClient::AppSpawnClient(bool isNWebSpawn)
30 {
31 socket_ = std::make_shared<AppSpawnSocket>(isNWebSpawn);
32 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
33 }
34
OpenConnection()35 ErrCode AppSpawnClient::OpenConnection()
36 {
37 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
38 if (!socket_) {
39 HILOG_ERROR("failed to open connection without socket!");
40 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
41 }
42
43 int32_t retryCount = 1;
44 ErrCode errCode = socket_->OpenAppSpawnConnection();
45 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
46 HILOG_WARN("failed to OpenConnection, retry times %{public}d ...", retryCount);
47 usleep(CONNECT_RETRY_DELAY);
48 errCode = socket_->OpenAppSpawnConnection();
49 retryCount++;
50 }
51 if (SUCCEEDED(errCode)) {
52 state_ = SpawnConnectionState::STATE_CONNECTED;
53 } else {
54 HILOG_ERROR("failed to openConnection, errorCode is %{public}08x", errCode);
55 state_ = SpawnConnectionState::STATE_CONNECT_FAILED;
56 }
57 return errCode;
58 }
59
PreStartNWebSpawnProcess()60 ErrCode AppSpawnClient::PreStartNWebSpawnProcess()
61 {
62 HILOG_INFO("PreStartNWebSpawnProcess");
63 int32_t retryCount = 1;
64 ErrCode errCode = PreStartNWebSpawnProcessImpl();
65 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
66 HILOG_ERROR("failed to Start NWebSpawn Process, retry times %{public}d ...", retryCount);
67 usleep(CONNECT_RETRY_DELAY);
68 errCode = PreStartNWebSpawnProcessImpl();
69 retryCount++;
70 }
71 return errCode;
72 }
73
PreStartNWebSpawnProcessImpl()74 ErrCode AppSpawnClient::PreStartNWebSpawnProcessImpl()
75 {
76 HILOG_INFO("PreStartNWebSpawnProcessImpl");
77 if (!socket_) {
78 HILOG_ERROR("failed to Pre Start NWebSpawn Process without socket!");
79 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
80 }
81
82 ErrCode result = ERR_OK;
83 // openconnection failed, return fail
84 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
85 result = OpenConnection();
86 if (FAILED(result)) {
87 HILOG_ERROR("connect to nwebspawn failed!");
88 return result;
89 }
90 }
91
92 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
93 this, [](AppSpawnClient *client) { client->CloseConnection(); });
94
95 return result;
96 }
97
StartProcess(const AppSpawnStartMsg & startMsg,pid_t & pid)98 ErrCode AppSpawnClient::StartProcess(const AppSpawnStartMsg &startMsg, pid_t &pid)
99 {
100 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
101 int32_t retryCount = 1;
102 ErrCode errCode = StartProcessImpl(startMsg, pid);
103 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
104 HILOG_WARN("failed to StartProcess, retry times %{public}d ...", retryCount);
105 usleep(CONNECT_RETRY_DELAY);
106 errCode = StartProcessImpl(startMsg, pid);
107 retryCount++;
108 }
109 return errCode;
110 }
111
StartProcessImpl(const AppSpawnStartMsg & startMsg,pid_t & pid)112 ErrCode AppSpawnClient::StartProcessImpl(const AppSpawnStartMsg &startMsg, pid_t &pid)
113 {
114 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
115 if (!socket_) {
116 HILOG_ERROR("failed to startProcess without socket!");
117 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
118 }
119
120 ErrCode result = ERR_OK;
121 // open connection failed, return fail
122 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
123 result = OpenConnection();
124 if (FAILED(result)) {
125 HILOG_ERROR("connect to appSpawn failed!");
126 return result;
127 }
128 }
129 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
130 this, [](AppSpawnClient *client) { client->CloseConnection(); });
131
132 AppSpawnMsgWrapper msgWrapper;
133 if (!msgWrapper.AssembleMsg(startMsg)) {
134 HILOG_ERROR("AssembleMsg failed!");
135 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
136 }
137 AppSpawnPidMsg pidMsg;
138 if (msgWrapper.IsValid()) {
139 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
140 if (FAILED(result)) {
141 HILOG_ERROR("WriteMessage failed!");
142 return result;
143 }
144 result = StartProcessForWriteMsg(msgWrapper, startMsg);
145 if (FAILED(result)) {
146 HILOG_ERROR("StartProcessForWriteMsg failed!");
147 return result;
148 }
149 result = WriteDataGroupInfoList(msgWrapper);
150 if (FAILED(result)) {
151 HILOG_ERROR("WriteDataGroupInfoList failed!");
152 return result;
153 }
154 result = socket_->ReadMessage(reinterpret_cast<void *>(pidMsg.pidBuf), LEN_PID);
155 if (FAILED(result)) {
156 HILOG_ERROR("ReadMessage failed!");
157 return result;
158 }
159 }
160 if (pidMsg.pid <= 0) {
161 HILOG_ERROR("invalid pid!");
162 result = ERR_APPEXECFWK_INVALID_PID;
163 } else {
164 pid = pidMsg.pid;
165 }
166 return result;
167 }
168
StartProcessForWriteMsg(const AppSpawnMsgWrapper & msgWrapper,const AppSpawnStartMsg & startMsg)169 ErrCode AppSpawnClient::StartProcessForWriteMsg(const AppSpawnMsgWrapper &msgWrapper, const AppSpawnStartMsg &startMsg)
170 {
171 ErrCode result = ERR_OK;
172 result = WriteStrInfoMessage(msgWrapper.GetHspListStr());
173 if (FAILED(result)) {
174 HILOG_ERROR("Write HspList failed!");
175 return result;
176 }
177 result = WriteStrInfoMessage(startMsg.overlayInfo);
178 if (FAILED(result)) {
179 HILOG_ERROR("Write OverlayInfo failed!");
180 return result;
181 }
182 return result;
183 }
184
WriteStrInfoMessage(const std::string & strInfo)185 ErrCode AppSpawnClient::WriteStrInfoMessage(const std::string &strInfo)
186 {
187 ErrCode result = ERR_OK;
188 if (strInfo.empty()) {
189 return result;
190 }
191
192 // split msg
193 const char *buff = strInfo.c_str();
194 size_t leftLen = strInfo.size() + 1;
195 HILOG_DEBUG("strInfo length is %zu", leftLen);
196 while (leftLen >= SOCK_MAX_SEND_BUFFER) {
197 result = socket_->WriteMessage(buff, SOCK_MAX_SEND_BUFFER);
198 if (FAILED(result)) {
199 return result;
200 }
201 buff += SOCK_MAX_SEND_BUFFER;
202 leftLen -= SOCK_MAX_SEND_BUFFER;
203 }
204
205 HILOG_DEBUG("strInfo: leftLen = %zu", leftLen);
206 if (leftLen > 0) {
207 result = socket_->WriteMessage(buff, leftLen);
208 }
209 return result;
210 }
211
WriteDataGroupInfoList(AppSpawnMsgWrapper & msgWrapper)212 ErrCode AppSpawnClient::WriteDataGroupInfoList(AppSpawnMsgWrapper &msgWrapper)
213 {
214 ErrCode result = ERR_OK;
215 const std::string& dataGroupInfoListStr = msgWrapper.GetDataGroupInfoListStr();
216 if (dataGroupInfoListStr.empty()) {
217 return result;
218 }
219
220 // split msg
221 const char *buff = dataGroupInfoListStr.c_str();
222 size_t leftLen = dataGroupInfoListStr.size() + 1;
223 HILOG_DEBUG("dataGroupInfoListStr length is %zu", leftLen);
224 result = socket_->WriteMessage(buff, leftLen);
225 return result;
226 }
227
GetRenderProcessTerminationStatus(const AppSpawnStartMsg & startMsg,int & status)228 ErrCode AppSpawnClient::GetRenderProcessTerminationStatus(const AppSpawnStartMsg &startMsg, int &status)
229 {
230 if (!socket_) {
231 HILOG_ERROR("socket_ is null!");
232 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
233 }
234
235 ErrCode result = ERR_OK;
236 // open connection failed, return fail
237 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
238 result = OpenConnection();
239 if (FAILED(result)) {
240 HILOG_ERROR("connect to appSpawn failed!");
241 return result;
242 }
243 }
244 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
245 this, [](AppSpawnClient *client) { client->CloseConnection(); });
246
247 AppSpawnMsgWrapper msgWrapper;
248 if (!msgWrapper.AssembleMsg(startMsg)) {
249 HILOG_ERROR("AssembleMsg failed!");
250 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
251 }
252 if (msgWrapper.IsValid()) {
253 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
254 if (FAILED(result)) {
255 HILOG_ERROR("WriteMessage failed!");
256 return result;
257 }
258 result = socket_->ReadMessage(reinterpret_cast<void *>(&status), sizeof(int));
259 if (FAILED(result)) {
260 HILOG_ERROR("ReadMessage failed!");
261 return result;
262 }
263 }
264 return result;
265 }
266
QueryConnectionState() const267 SpawnConnectionState AppSpawnClient::QueryConnectionState() const
268 {
269 return state_;
270 }
271
CloseConnection()272 void AppSpawnClient::CloseConnection()
273 {
274 if (socket_ && state_ == SpawnConnectionState::STATE_CONNECTED) {
275 socket_->CloseAppSpawnConnection();
276 }
277 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
278 }
279
SetSocket(const std::shared_ptr<AppSpawnSocket> socket)280 void AppSpawnClient::SetSocket(const std::shared_ptr<AppSpawnSocket> socket)
281 {
282 socket_ = socket;
283 }
284 } // namespace AppExecFwk
285 } // namespace OHOS
286