xref: /aosp_15_r20/frameworks/native/libs/gui/tests/testserver/TestServerClient.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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