1 /*
2 * Copyright (c) 2021 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 "bytrace.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 BYTRACE_NAME(BYTRACE_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
StartProcess(const AppSpawnStartMsg & startMsg,pid_t & pid)59 ErrCode AppSpawnClient::StartProcess(const AppSpawnStartMsg &startMsg, pid_t &pid)
60 {
61 BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
62 int32_t retryCount = 1;
63 ErrCode errCode = StartProcessImpl(startMsg, pid);
64 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
65 HILOG_WARN("failed to StartProcess, retry times %{public}d ...", retryCount);
66 usleep(CONNECT_RETRY_DELAY);
67 errCode = StartProcessImpl(startMsg, pid);
68 retryCount++;
69 }
70 return errCode;
71 }
72
StartProcessImpl(const AppSpawnStartMsg & startMsg,pid_t & pid)73 ErrCode AppSpawnClient::StartProcessImpl(const AppSpawnStartMsg &startMsg, pid_t &pid)
74 {
75 BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
76 if (!socket_) {
77 HILOG_ERROR("failed to startProcess 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 appspawn failed!");
87 return result;
88 }
89 }
90 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
91 this, [](AppSpawnClient *client) { client->CloseConnection(); });
92
93 AppSpawnMsgWrapper msgWrapper;
94 if (!msgWrapper.AssembleMsg(startMsg)) {
95 HILOG_ERROR("AssembleMsg failed!");
96 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
97 }
98 AppSpawnPidMsg pidMsg;
99 if (msgWrapper.IsValid()) {
100 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
101 if (FAILED(result)) {
102 HILOG_ERROR("WriteMessage failed!");
103 return result;
104 }
105 result = socket_->ReadMessage(reinterpret_cast<void *>(pidMsg.pidBuf), LEN_PID);
106 if (FAILED(result)) {
107 HILOG_ERROR("ReadMessage failed!");
108 return result;
109 }
110 }
111 if (pidMsg.pid <= 0) {
112 HILOG_ERROR("invalid pid!");
113 result = ERR_APPEXECFWK_INVALID_PID;
114 } else {
115 pid = pidMsg.pid;
116 }
117 return result;
118 }
119
GetRenderProcessTerminationStatus(const AppSpawnStartMsg & startMsg,int & status)120 ErrCode AppSpawnClient::GetRenderProcessTerminationStatus(const AppSpawnStartMsg &startMsg, int &status)
121 {
122 if (!socket_) {
123 HILOG_ERROR("socket_ is null!");
124 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
125 }
126
127 ErrCode result = ERR_OK;
128 // openconnection failed, return fail
129 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
130 result = OpenConnection();
131 if (FAILED(result)) {
132 HILOG_ERROR("connect to appspawn failed!");
133 return result;
134 }
135 }
136 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
137 this, [](AppSpawnClient *client) { client->CloseConnection(); });
138
139 AppSpawnMsgWrapper msgWrapper;
140 if (!msgWrapper.AssembleMsg(startMsg)) {
141 HILOG_ERROR("AssembleMsg failed!");
142 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
143 }
144 if (msgWrapper.IsValid()) {
145 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
146 if (FAILED(result)) {
147 HILOG_ERROR("WriteMessage failed!");
148 return result;
149 }
150 result = socket_->ReadMessage(reinterpret_cast<void *>(&status), sizeof(int));
151 if (FAILED(result)) {
152 HILOG_ERROR("ReadMessage failed!");
153 return result;
154 }
155 }
156 return result;
157 }
158
QueryConnectionState() const159 SpawnConnectionState AppSpawnClient::QueryConnectionState() const
160 {
161 return state_;
162 }
163
CloseConnection()164 void AppSpawnClient::CloseConnection()
165 {
166 if (socket_ && state_ == SpawnConnectionState::STATE_CONNECTED) {
167 socket_->CloseAppSpawnConnection();
168 }
169 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
170 }
171
SetSocket(const std::shared_ptr<AppSpawnSocket> socket)172 void AppSpawnClient::SetSocket(const std::shared_ptr<AppSpawnSocket> socket)
173 {
174 socket_ = socket;
175 }
176 } // namespace AppExecFwk
177 } // namespace OHOS
178