1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sys/wait.h>
18 #include <cerrno>
19 #define LOG_TAG "TestServerClient"
20
21 #include <android-base/stringprintf.h>
22 #include <binder/IServiceManager.h>
23 #include <binder/ProcessState.h>
24 #include <libgui_test_server/ITestServer.h>
25 #include <log/log.h>
26 #include <utils/Errors.h>
27
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include <atomic>
35 #include <csignal>
36 #include <cstdlib>
37 #include <mutex>
38 #include <string>
39
40 #include "TestServerClient.h"
41 #include "TestServerCommon.h"
42
43 namespace android {
44
45 namespace {
46
GetUniqueServiceName()47 std::string GetUniqueServiceName() {
48 static std::atomic<int> uniqueId = 1;
49
50 pid_t pid = getpid();
51 int id = uniqueId++;
52 return base::StringPrintf("Libgui-TestServer-%d-%d", pid, id);
53 }
54
55 struct RemoteTestServerHostHolder {
RemoteTestServerHostHolderandroid::__anona02f37b70111::RemoteTestServerHostHolder56 RemoteTestServerHostHolder(pid_t pid, int sendFd, int recvFd)
57 : mPid(pid), mSendFd(sendFd), mRecvFd(recvFd) {}
~RemoteTestServerHostHolderandroid::__anona02f37b70111::RemoteTestServerHostHolder58 ~RemoteTestServerHostHolder() {
59 std::lock_guard lock(mMutex);
60
61 kill(mPid, SIGKILL);
62 close(mSendFd);
63 close(mRecvFd);
64 }
65
CreateTestServerOrDieandroid::__anona02f37b70111::RemoteTestServerHostHolder66 pid_t CreateTestServerOrDie(std::string name) {
67 std::lock_guard lock(mMutex);
68
69 CreateServerRequest request;
70 strlcpy(request.name, name.c_str(), sizeof(request.name) / sizeof(request.name[0]));
71
72 ssize_t bytes = write(mSendFd, &request, sizeof(request));
73 LOG_ALWAYS_FATAL_IF(bytes != sizeof(request));
74
75 CreateServerResponse response;
76 bytes = read(mRecvFd, &response, sizeof(response));
77 LOG_ALWAYS_FATAL_IF(bytes != sizeof(response));
78
79 return response.pid;
80 }
81
82 private:
83 std::mutex mMutex;
84
85 pid_t mPid;
86 int mSendFd;
87 int mRecvFd;
88 };
89
90 std::unique_ptr<RemoteTestServerHostHolder> g_remoteTestServerHostHolder = nullptr;
91
92 } // namespace
93
InitializeOrDie(const char * filename)94 void TestServerClient::InitializeOrDie(const char* filename) {
95 int sendPipeFds[2];
96 int ret = pipe(sendPipeFds);
97 LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess send pipe");
98
99 int recvPipeFds[2];
100 ret = pipe(recvPipeFds);
101 LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess recv pipe");
102
103 pid_t childPid = fork();
104 LOG_ALWAYS_FATAL_IF(childPid < 0, "Unable to fork child process");
105
106 if (childPid == 0) {
107 // We forked!
108 close(sendPipeFds[1]);
109 close(recvPipeFds[0]);
110
111 // We'll be reading from the parent's "send" and writing to the parent's "recv".
112 std::string sendPipe = std::to_string(sendPipeFds[0]);
113 std::string recvPipe = std::to_string(recvPipeFds[1]);
114 char* args[] = {
115 const_cast<char*>(filename),
116 const_cast<char*>("--test-server-host"),
117 const_cast<char*>(sendPipe.c_str()),
118 const_cast<char*>(recvPipe.c_str()),
119 nullptr,
120 };
121
122 ret = execv(filename, args);
123 ALOGE("Failed to exec libguiTestServer. ret=%d errno=%d (%s)", ret, errno, strerror(errno));
124 status_t status = -errno;
125 write(recvPipeFds[1], &status, sizeof(status));
126 _exit(EXIT_FAILURE);
127 }
128
129 close(sendPipeFds[0]);
130 close(recvPipeFds[1]);
131
132 // Check for an OK status that the host started. If so, we're good to go.
133 status_t status;
134 ret = read(recvPipeFds[0], &status, sizeof(status));
135 LOG_ALWAYS_FATAL_IF(ret != sizeof(status), "Unable to read from pipe: %d", ret);
136 LOG_ALWAYS_FATAL_IF(OK != status, "Pipe returned failed status: %d", status);
137
138 g_remoteTestServerHostHolder =
139 std::make_unique<RemoteTestServerHostHolder>(childPid, sendPipeFds[1], recvPipeFds[0]);
140 }
141
Create()142 sp<TestServerClient> TestServerClient::Create() {
143 std::string serviceName = GetUniqueServiceName();
144
145 pid_t childPid = g_remoteTestServerHostHolder->CreateTestServerOrDie(serviceName);
146 ALOGD("Created child server %s with pid %d", serviceName.c_str(), childPid);
147
148 sp<libgui_test_server::ITestServer> server =
149 waitForService<libgui_test_server::ITestServer>(String16(serviceName.c_str()));
150 LOG_ALWAYS_FATAL_IF(server == nullptr);
151 ALOGD("Created connected to child server %s", serviceName.c_str());
152
153 return sp<TestServerClient>::make(server);
154 }
155
TestServerClient(const sp<libgui_test_server::ITestServer> & server)156 TestServerClient::TestServerClient(const sp<libgui_test_server::ITestServer>& server)
157 : mServer(server) {}
158
~TestServerClient()159 TestServerClient::~TestServerClient() {
160 Kill();
161 }
162
CreateProducer()163 sp<IGraphicBufferProducer> TestServerClient::CreateProducer() {
164 std::lock_guard<std::mutex> lock(mMutex);
165
166 if (!mIsAlive) {
167 return nullptr;
168 }
169
170 view::Surface surface;
171 binder::Status status = mServer->createProducer(&surface);
172
173 if (!status.isOk()) {
174 ALOGE("Failed to create remote producer. Error: %s", status.exceptionMessage().c_str());
175 return nullptr;
176 }
177
178 if (!surface.graphicBufferProducer) {
179 ALOGE("Remote producer returned no IGBP.");
180 return nullptr;
181 }
182
183 return surface.graphicBufferProducer;
184 }
185
Kill()186 status_t TestServerClient::Kill() {
187 std::lock_guard<std::mutex> lock(mMutex);
188 if (!mIsAlive) {
189 return DEAD_OBJECT;
190 }
191
192 mServer->killNow();
193 mServer = nullptr;
194 mIsAlive = false;
195
196 return OK;
197 }
198
199 } // namespace android
200