/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #define LOG_TAG "TestServerClient" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TestServerClient.h" #include "TestServerCommon.h" namespace android { namespace { std::string GetUniqueServiceName() { static std::atomic uniqueId = 1; pid_t pid = getpid(); int id = uniqueId++; return base::StringPrintf("Libgui-TestServer-%d-%d", pid, id); } struct RemoteTestServerHostHolder { RemoteTestServerHostHolder(pid_t pid, int sendFd, int recvFd) : mPid(pid), mSendFd(sendFd), mRecvFd(recvFd) {} ~RemoteTestServerHostHolder() { std::lock_guard lock(mMutex); kill(mPid, SIGKILL); close(mSendFd); close(mRecvFd); } pid_t CreateTestServerOrDie(std::string name) { std::lock_guard lock(mMutex); CreateServerRequest request; strlcpy(request.name, name.c_str(), sizeof(request.name) / sizeof(request.name[0])); ssize_t bytes = write(mSendFd, &request, sizeof(request)); LOG_ALWAYS_FATAL_IF(bytes != sizeof(request)); CreateServerResponse response; bytes = read(mRecvFd, &response, sizeof(response)); LOG_ALWAYS_FATAL_IF(bytes != sizeof(response)); return response.pid; } private: std::mutex mMutex; pid_t mPid; int mSendFd; int mRecvFd; }; std::unique_ptr g_remoteTestServerHostHolder = nullptr; } // namespace void TestServerClient::InitializeOrDie(const char* filename) { int sendPipeFds[2]; int ret = pipe(sendPipeFds); LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess send pipe"); int recvPipeFds[2]; ret = pipe(recvPipeFds); LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess recv pipe"); pid_t childPid = fork(); LOG_ALWAYS_FATAL_IF(childPid < 0, "Unable to fork child process"); if (childPid == 0) { // We forked! close(sendPipeFds[1]); close(recvPipeFds[0]); // We'll be reading from the parent's "send" and writing to the parent's "recv". std::string sendPipe = std::to_string(sendPipeFds[0]); std::string recvPipe = std::to_string(recvPipeFds[1]); char* args[] = { const_cast(filename), const_cast("--test-server-host"), const_cast(sendPipe.c_str()), const_cast(recvPipe.c_str()), nullptr, }; ret = execv(filename, args); ALOGE("Failed to exec libguiTestServer. ret=%d errno=%d (%s)", ret, errno, strerror(errno)); status_t status = -errno; write(recvPipeFds[1], &status, sizeof(status)); _exit(EXIT_FAILURE); } close(sendPipeFds[0]); close(recvPipeFds[1]); // Check for an OK status that the host started. If so, we're good to go. status_t status; ret = read(recvPipeFds[0], &status, sizeof(status)); LOG_ALWAYS_FATAL_IF(ret != sizeof(status), "Unable to read from pipe: %d", ret); LOG_ALWAYS_FATAL_IF(OK != status, "Pipe returned failed status: %d", status); g_remoteTestServerHostHolder = std::make_unique(childPid, sendPipeFds[1], recvPipeFds[0]); } sp TestServerClient::Create() { std::string serviceName = GetUniqueServiceName(); pid_t childPid = g_remoteTestServerHostHolder->CreateTestServerOrDie(serviceName); ALOGD("Created child server %s with pid %d", serviceName.c_str(), childPid); sp server = waitForService(String16(serviceName.c_str())); LOG_ALWAYS_FATAL_IF(server == nullptr); ALOGD("Created connected to child server %s", serviceName.c_str()); return sp::make(server); } TestServerClient::TestServerClient(const sp& server) : mServer(server) {} TestServerClient::~TestServerClient() { Kill(); } sp TestServerClient::CreateProducer() { std::lock_guard lock(mMutex); if (!mIsAlive) { return nullptr; } view::Surface surface; binder::Status status = mServer->createProducer(&surface); if (!status.isOk()) { ALOGE("Failed to create remote producer. Error: %s", status.exceptionMessage().c_str()); return nullptr; } if (!surface.graphicBufferProducer) { ALOGE("Remote producer returned no IGBP."); return nullptr; } return surface.graphicBufferProducer; } status_t TestServerClient::Kill() { std::lock_guard lock(mMutex); if (!mIsAlive) { return DEAD_OBJECT; } mServer->killNow(); mServer = nullptr; mIsAlive = false; return OK; } } // namespace android