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