1 // Copyright (C) 2024 The Android Open Source Project
2 //
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 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 #include "KumquatInstance.h"
19 
20 #include <unistd.h>
21 
22 #include <filesystem>
23 
24 #include "aemu/base/Path.h"
25 
26 using testing::Eq;
27 
28 namespace gfxstream {
29 namespace tests {
30 
KumquatInstance()31 KumquatInstance::KumquatInstance() {}
32 
SetUp(bool withGl,bool withVk,std::string features)33 void KumquatInstance::SetUp(bool withGl, bool withVk, std::string features) {
34     const std::filesystem::path testDirectory = gfxstream::guest::getProgramDirectory();
35     const std::string kumquatCommand = (testDirectory / "kumquat").string();
36     const std::string renderer_features = "--renderer-features=" + features;
37 
38     std::string capset_names = "--capset-names=";
39     if (withGl) {
40         capset_names.append("gfxstream-gles:");
41     }
42     if (withVk) {
43         capset_names.append("gfxstream-vulkan:");
44     }
45 
46     int fds[2];
47     ASSERT_THAT(pipe(fds), Eq(0));
48 
49     // VirtGpuKumquatDevice.cpp by default connects to "/tmp/kumquat-gpu-0".  If this changes,
50     // the correct socket path must be plumbed through to VirtGpuKumquatDevice.cpp
51     const std::string gpu_socket_path = "/tmp/kumquat-gpu-" + std::to_string(0);
52 
53     const std::string gpu_socket_cmd = "--gpu-socket-path=" + gpu_socket_path;
54 
55     const std::string pipe_descriptor = "--pipe-descriptor=" + std::to_string(fds[1]);
56 
57     pid_t pid = fork();
58     if (pid == 0) {
59         close(fds[0]);
60         execl(kumquatCommand.c_str(), kumquatCommand.c_str(), gpu_socket_cmd.c_str(),
61               capset_names.c_str(), renderer_features.c_str(), pipe_descriptor.c_str(), nullptr);
62         exit(0);
63     } else {
64         close(fds[1]);
65         uint64_t count = 0;
66         ssize_t bytes_read = read(fds[0], &count, sizeof(count));
67         // Kumquat writes [uint64_t](1) to the write end of the pipe..
68         ASSERT_THAT(bytes_read, Eq(8));
69         close(fds[0]);
70         ASSERT_THAT(virtgpu_kumquat_init(&mVirtGpu, gpu_socket_path.c_str()), Eq(0));
71         mKumquatPid = pid;
72     }
73 }
74 
~KumquatInstance()75 KumquatInstance::~KumquatInstance() {
76     virtgpu_kumquat_finish(&mVirtGpu);
77     kill(mKumquatPid, SIGKILL);
78     int status = 0;
79     pid_t pid = waitpid(mKumquatPid, &status, WNOHANG);
80     while (!pid) {
81         pid = waitpid(mKumquatPid, &status, WNOHANG);
82     }
83 }
84 
Snapshot()85 void KumquatInstance::Snapshot() { ASSERT_THAT(virtgpu_kumquat_snapshot_save(mVirtGpu), Eq(0)); }
86 
Restore()87 void KumquatInstance::Restore() { ASSERT_THAT(virtgpu_kumquat_snapshot_restore(mVirtGpu), Eq(0)); }
88 
89 }  // namespace tests
90 }  // namespace gfxstream
91