1 /*
2 * Copyright (c) 2021-2022 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 } // namespace
27
AppSpawnClient(bool isNWebSpawn)28 AppSpawnClient::AppSpawnClient(bool isNWebSpawn)
29 {
30 socket_ = std::make_shared<AppSpawnSocket>(isNWebSpawn);
31 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
32 }
33
OpenConnection()34 ErrCode AppSpawnClient::OpenConnection()
35 {
36 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
37 if (!socket_) {
38 HILOG_ERROR("failed to open connection without socket!");
39 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
40 }
41
42 int32_t retryCount = 1;
43 ErrCode errCode = socket_->OpenAppSpawnConnection();
44 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
45 HILOG_WARN("failed to OpenConnection, retry times %{public}d ...", retryCount);
46 usleep(CONNECT_RETRY_DELAY);
47 errCode = socket_->OpenAppSpawnConnection();
48 retryCount++;
49 }
50 if (SUCCEEDED(errCode)) {
51 state_ = SpawnConnectionState::STATE_CONNECTED;
52 } else {
53 HILOG_ERROR("failed to openConnection, errorCode is %{public}08x", errCode);
54 state_ = SpawnConnectionState::STATE_CONNECT_FAILED;
55 }
56 return errCode;
57 }
58
PreStartNWebSpawnProcess()59 ErrCode AppSpawnClient::PreStartNWebSpawnProcess()
60 {
61 HILOG_INFO("PreStartNWebSpawnProcess");
62 int32_t retryCount = 1;
63 ErrCode errCode = PreStartNWebSpawnProcessImpl();
64 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
65 HILOG_ERROR("failed to Start NWebSpawn Process, retry times %{public}d ...", retryCount);
66 usleep(CONNECT_RETRY_DELAY);
67 errCode = PreStartNWebSpawnProcessImpl();
68 retryCount++;
69 }
70 return errCode;
71 }
72
PreStartNWebSpawnProcessImpl()73 ErrCode AppSpawnClient::PreStartNWebSpawnProcessImpl()
74 {
75 HILOG_INFO("PreStartNWebSpawnProcessImpl");
76 if (!socket_) {
77 HILOG_ERROR("failed to Pre Start NWebSpawn Process without socket!");
78 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
79 }
80
81 ErrCode result = ERR_OK;
82 // openconnection failed, return fail
83 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
84 result = OpenConnection();
85 if (FAILED(result)) {
86 HILOG_ERROR("connect to nwebspawn failed!");
87 return result;
88 }
89 }
90
91 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
92 this, [](AppSpawnClient *client) { client->CloseConnection(); });
93
94 return result;
95 }
96
StartProcess(const AppSpawnStartMsg & startMsg,pid_t & pid)97 ErrCode AppSpawnClient::StartProcess(const AppSpawnStartMsg &startMsg, pid_t &pid)
98 {
99 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
100 int32_t retryCount = 1;
101 ErrCode errCode = StartProcessImpl(startMsg, pid);
102 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
103 HILOG_WARN("failed to StartProcess, retry times %{public}d ...", retryCount);
104 usleep(CONNECT_RETRY_DELAY);
105 errCode = StartProcessImpl(startMsg, pid);
106 retryCount++;
107 }
108 return errCode;
109 }
110
StartProcessImpl(const AppSpawnStartMsg & startMsg,pid_t & pid)111 ErrCode AppSpawnClient::StartProcessImpl(const AppSpawnStartMsg &startMsg, pid_t &pid)
112 {
113 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
114 if (!socket_) {
115 HILOG_ERROR("failed to startProcess without socket!");
116 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
117 }
118
119 ErrCode result = ERR_OK;
120 // open connection failed, return fail
121 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
122 result = OpenConnection();
123 if (FAILED(result)) {
124 HILOG_ERROR("connect to appSpawn failed!");
125 return result;
126 }
127 }
128 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
129 this, [](AppSpawnClient *client) { client->CloseConnection(); });
130
131 AppSpawnMsgWrapper msgWrapper;
132 if (!msgWrapper.AssembleMsg(startMsg)) {
133 HILOG_ERROR("AssembleMsg failed!");
134 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
135 }
136 AppSpawnPidMsg pidMsg;
137 if (msgWrapper.IsValid()) {
138 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
139 if (FAILED(result)) {
140 HILOG_ERROR("WriteMessage failed!");
141 return result;
142 }
143 result = socket_->ReadMessage(reinterpret_cast<void *>(pidMsg.pidBuf), LEN_PID);
144 if (FAILED(result)) {
145 HILOG_ERROR("ReadMessage failed!");
146 return result;
147 }
148 }
149 if (pidMsg.pid <= 0) {
150 HILOG_ERROR("invalid pid!");
151 result = ERR_APPEXECFWK_INVALID_PID;
152 } else {
153 pid = pidMsg.pid;
154 }
155 return result;
156 }
157
GetRenderProcessTerminationStatus(const AppSpawnStartMsg & startMsg,int & status)158 ErrCode AppSpawnClient::GetRenderProcessTerminationStatus(const AppSpawnStartMsg &startMsg, int &status)
159 {
160 if (!socket_) {
161 HILOG_ERROR("socket_ is null!");
162 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
163 }
164
165 ErrCode result = ERR_OK;
166 // open connection failed, return fail
167 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
168 result = OpenConnection();
169 if (FAILED(result)) {
170 HILOG_ERROR("connect to appSpawn failed!");
171 return result;
172 }
173 }
174 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
175 this, [](AppSpawnClient *client) { client->CloseConnection(); });
176
177 AppSpawnMsgWrapper msgWrapper;
178 if (!msgWrapper.AssembleMsg(startMsg)) {
179 HILOG_ERROR("AssembleMsg failed!");
180 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
181 }
182 if (msgWrapper.IsValid()) {
183 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
184 if (FAILED(result)) {
185 HILOG_ERROR("WriteMessage failed!");
186 return result;
187 }
188 result = socket_->ReadMessage(reinterpret_cast<void *>(&status), sizeof(int));
189 if (FAILED(result)) {
190 HILOG_ERROR("ReadMessage failed!");
191 return result;
192 }
193 }
194 return result;
195 }
196
QueryConnectionState() const197 SpawnConnectionState AppSpawnClient::QueryConnectionState() const
198 {
199 return state_;
200 }
201
CloseConnection()202 void AppSpawnClient::CloseConnection()
203 {
204 if (socket_ && state_ == SpawnConnectionState::STATE_CONNECTED) {
205 socket_->CloseAppSpawnConnection();
206 }
207 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
208 }
209
SetSocket(const std::shared_ptr<AppSpawnSocket> socket)210 void AppSpawnClient::SetSocket(const std::shared_ptr<AppSpawnSocket> socket)
211 {
212 socket_ = socket;
213 }
214 } // namespace AppExecFwk
215 } // namespace OHOS
216