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 "app_log_wrapper.h"
19
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 const int32_t CONNECT_RETRY_DELAY = 200 * 1000; // 200ms
24 const int32_t CONNECT_RETRY_MAX_TIMES = 15;
25 } // namespace
26
AppSpawnClient()27 AppSpawnClient::AppSpawnClient()
28 {
29 socket_ = std::make_shared<AppSpawnSocket>();
30 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
31 }
32
OpenConnection()33 ErrCode AppSpawnClient::OpenConnection()
34 {
35 if (!socket_) {
36 APP_LOGE("failed to open connection without socket!");
37 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
38 }
39
40 int32_t retryCount = 1;
41 ErrCode errCode = socket_->OpenAppSpawnConnection();
42 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
43 APP_LOGW("failed to OpenConnection, retry times %{public}d ...", retryCount);
44 usleep(CONNECT_RETRY_DELAY);
45 errCode = socket_->OpenAppSpawnConnection();
46 retryCount++;
47 }
48 if (SUCCEEDED(errCode)) {
49 state_ = SpawnConnectionState::STATE_CONNECTED;
50 } else {
51 APP_LOGE("failed to openConnection, errorCode is %{public}08x", errCode);
52 state_ = SpawnConnectionState::STATE_CONNECT_FAILED;
53 }
54 return errCode;
55 }
56
StartProcess(const AppSpawnStartMsg & startMsg,pid_t & pid)57 ErrCode AppSpawnClient::StartProcess(const AppSpawnStartMsg &startMsg, pid_t &pid)
58 {
59 int32_t retryCount = 1;
60 ErrCode errCode = StartProcessImpl(startMsg, pid);
61 while (FAILED(errCode) && retryCount <= CONNECT_RETRY_MAX_TIMES) {
62 APP_LOGW("failed to StartProcess, retry times %{public}d ...", retryCount);
63 usleep(CONNECT_RETRY_DELAY);
64 errCode = StartProcessImpl(startMsg, pid);
65 retryCount++;
66 }
67 return errCode;
68 }
69
StartProcessImpl(const AppSpawnStartMsg & startMsg,pid_t & pid)70 ErrCode AppSpawnClient::StartProcessImpl(const AppSpawnStartMsg &startMsg, pid_t &pid)
71 {
72 if (!socket_) {
73 APP_LOGE("failed to startProcess without socket!");
74 return ERR_APPEXECFWK_BAD_APPSPAWN_SOCKET;
75 }
76
77 ErrCode result = ERR_OK;
78 // openconnection failed, return fail
79 if (state_ != SpawnConnectionState::STATE_CONNECTED) {
80 result = OpenConnection();
81 if (FAILED(result)) {
82 APP_LOGE("connect to appspawn failed!");
83 return result;
84 }
85 }
86 std::unique_ptr<AppSpawnClient, void (*)(AppSpawnClient *)> autoCloseConnection(
87 this, [](AppSpawnClient *client) { client->CloseConnection(); });
88
89 AppSpawnMsgWrapper msgWrapper;
90 if (!msgWrapper.AssembleMsg(startMsg)) {
91 APP_LOGE("AssembleMsg failed!");
92 return ERR_APPEXECFWK_ASSEMBLE_START_MSG_FAILED;
93 }
94 AppSpawnPidMsg pidMsg;
95 if (msgWrapper.IsValid()) {
96 result = socket_->WriteMessage(msgWrapper.GetMsgBuf(), msgWrapper.GetMsgLength());
97 if (FAILED(result)) {
98 APP_LOGE("WriteMessage failed!");
99 return result;
100 }
101 result = socket_->ReadMessage(reinterpret_cast<void *>(pidMsg.pidBuf), LEN_PID);
102 if (FAILED(result)) {
103 APP_LOGE("ReadMessage failed!");
104 return result;
105 }
106 }
107 if (pidMsg.pid <= 0) {
108 APP_LOGE("invalid pid!");
109 result = ERR_APPEXECFWK_INVALID_PID;
110 } else {
111 pid = pidMsg.pid;
112 }
113 return result;
114 }
115
QueryConnectionState() const116 SpawnConnectionState AppSpawnClient::QueryConnectionState() const
117 {
118 return state_;
119 }
120
CloseConnection()121 void AppSpawnClient::CloseConnection()
122 {
123 if (socket_ && state_ == SpawnConnectionState::STATE_CONNECTED) {
124 socket_->CloseAppSpawnConnection();
125 }
126 state_ = SpawnConnectionState::STATE_NOT_CONNECT;
127 }
128
SetSocket(const std::shared_ptr<AppSpawnSocket> socket)129 void AppSpawnClient::SetSocket(const std::shared_ptr<AppSpawnSocket> socket)
130 {
131 socket_ = socket;
132 }
133 } // namespace AppExecFwk
134 } // namespace OHOS
135