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