1 // Copyright (C) 2018 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 #pragma once
15 
16 #include "aemu/base/Result.h"
17 #include "aemu/base/files/Stream.h"
18 #include "host-common/android_pipe_base.h"
19 
20 #include <cstdint>
21 #include <functional>
22 #include <unordered_map>
23 #include <unordered_set>
24 #include <vector>
25 #include <memory>
26 
27 #include <sys/types.h>
28 
29 // Fake pipe driver and device for testing goldfish pipe on host without
30 // running a VM.
31 namespace android {
32 
33 class HostGoldfishPipeDevice {
34 public:
35     static constexpr int kNoFd = -1;
36 
37     using ReadResult = android::base::Result<std::vector<uint8_t>, int>;
38     using WriteResult = android::base::Result<ssize_t, int>;
39 
40     HostGoldfishPipeDevice();
41     ~HostGoldfishPipeDevice();
42 
43     int getErrno() const;
44 
45     // Opens/closes pipe services.
46     int connect(const char* name);
47     void close(int fd);
48 
49     // Read/write for a particular pipe, along with C++ versions.
50     ssize_t read(int fd, void* buffer, size_t len);
51     ssize_t write(int fd, const void* buffer, size_t len);
52     ReadResult read(int fd, size_t maxLength);
53     WriteResult write(int fd, const std::vector<uint8_t>& data);
54     unsigned poll(int fd) const;
55 
56     // Sets a callback that will be invoked when the pipe is signaled by the
57     // host, accepts an "int wakes" parameter that matches contains PIPE_WAKE_*
58     // flags.
59     void setWakeCallback(int fd, std::function<void(int)> callback);
60 
61     // Gets the host side pipe object corresponding to hwpipe.
62     // Not persistent across snapshot save/load.
63     void* getHostPipe(int fd) const;
64 
65     // Saves/loads the entire set of pipes including pre/post save/load.
66     void saveSnapshot(base::Stream* stream);
67     void loadSnapshot(base::Stream* stream);
68 
69     // Save/load the device, but only for a particular hwpipe.
70     void saveSnapshot(base::Stream* stream, int fd);
71     int loadSnapshotSinglePipe(base::Stream* stream);
72 
73     // Closes all pipes and resets to initial state.
74     void clear();
75 
76     static HostGoldfishPipeDevice* get();
77 
78 private:
79     void initialize();
80 
81     struct InternalPipe {};
82 
83     struct HostHwPipe {
84         explicit HostHwPipe(int fd);
85         ~HostHwPipe();
86 
getFdHostHwPipe87         int getFd() const { return mFd; }
88 
89         static std::unique_ptr<HostHwPipe> create(int fd);
90 
91     private:
92         static const AndroidPipeHwFuncs vtbl;
93 
94         const AndroidPipeHwFuncs* const vtblPtr;
95         int mFd;
96     };
97 
98     friend HostHwPipe;
99 
100     struct FdInfo {
101         std::unique_ptr<HostHwPipe> hwPipe;
102         InternalPipe* hostPipe = nullptr;
103         std::function<void(int)> wakeCallback = [](int){};
104     };
105 
106     void clearLocked();
107 
108     FdInfo* lookupFdInfo(int fd);
109     const FdInfo* lookupFdInfo(int fd) const;
110 
111     HostHwPipe* associatePipes(std::unique_ptr<HostHwPipe> hwPipe,
112                                InternalPipe* hostPipe);
113     bool eraseFdInfo(int fd);
114 
115     ssize_t writeInternal(InternalPipe** pipe, const void* buffer, size_t len);
116 
117     void setErrno(ssize_t res);
118 
119     // Wake a hwpipe.
120     void signalWake(int fd, int wakes);
121 
122     // Callbacks for AndroidPipeHwFuncs.
123     static void closeFromHostCallback(void* hwpipe);
124     static void signalWakeCallback(void* hwpipe, unsigned wakes);
125     static int getPipeIdCallback(void* hwpipe);
126 
127     bool mInitialized = false;
128     int mFdGenerator = 0;
129     int mErrno = 0;
130 
131     std::unordered_map<InternalPipe*, HostHwPipe*> mPipeToHwPipe;
132     std::unordered_map<int, FdInfo> mFdInfo;
133 };
134 
135 // Initializes a global pipe instance for the current process.
136 HostGoldfishPipeDevice* getHostPipeInstance();
137 
138 } // namespace android
139 
140