You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.0 KiB

// Copyright (C) 2018 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.
#pragma once
#include "base/Result.h"
#include "base/Stream.h"
#include "host-common/android_pipe_base.h"
#include <cstdint>
#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <memory>
#include <sys/types.h>
// Fake pipe driver and device for testing goldfish pipe on host without
// running a VM.
namespace android {
class HostGoldfishPipeDevice {
public:
static constexpr int kNoFd = -1;
using ReadResult = android::base::Result<std::vector<uint8_t>, int>;
using WriteResult = android::base::Result<ssize_t, int>;
HostGoldfishPipeDevice();
~HostGoldfishPipeDevice();
int getErrno() const;
// Opens/closes pipe services.
int connect(const char* name);
void close(int fd);
// Read/write for a particular pipe, along with C++ versions.
ssize_t read(int fd, void* buffer, size_t len);
ssize_t write(int fd, const void* buffer, size_t len);
ReadResult read(int fd, size_t maxLength);
WriteResult write(int fd, const std::vector<uint8_t>& data);
unsigned poll(int fd) const;
// Sets a callback that will be invoked when the pipe is signaled by the
// host, accepts an "int wakes" parameter that matches contains PIPE_WAKE_*
// flags.
void setWakeCallback(int fd, std::function<void(int)> callback);
// Gets the host side pipe object corresponding to hwpipe.
// Not persistent across snapshot save/load.
void* getHostPipe(int fd) const;
// Saves/loads the entire set of pipes including pre/post save/load.
void saveSnapshot(base::Stream* stream);
void loadSnapshot(base::Stream* stream);
// Save/load the device, but only for a particular hwpipe.
void saveSnapshot(base::Stream* stream, int fd);
int loadSnapshotSinglePipe(base::Stream* stream);
// Closes all pipes and resets to initial state.
void clear();
static HostGoldfishPipeDevice* get();
private:
void initialize();
struct InternalPipe {};
struct HostHwPipe {
explicit HostHwPipe(int fd);
~HostHwPipe();
int getFd() const { return mFd; }
static std::unique_ptr<HostHwPipe> create(int fd);
private:
static const AndroidPipeHwFuncs vtbl;
const AndroidPipeHwFuncs* const vtblPtr;
int mFd;
};
friend HostHwPipe;
struct FdInfo {
std::unique_ptr<HostHwPipe> hwPipe;
InternalPipe* hostPipe = nullptr;
std::function<void(int)> wakeCallback = [](int){};
};
void clearLocked();
FdInfo* lookupFdInfo(int fd);
const FdInfo* lookupFdInfo(int fd) const;
HostHwPipe* associatePipes(std::unique_ptr<HostHwPipe> hwPipe,
InternalPipe* hostPipe);
bool eraseFdInfo(int fd);
ssize_t writeInternal(InternalPipe** pipe, const void* buffer, size_t len);
void setErrno(ssize_t res);
// Wake a hwpipe.
void signalWake(int fd, int wakes);
// Callbacks for AndroidPipeHwFuncs.
static void closeFromHostCallback(void* hwpipe);
static void signalWakeCallback(void* hwpipe, unsigned wakes);
static int getPipeIdCallback(void* hwpipe);
bool mInitialized = false;
int mFdGenerator = 0;
int mErrno = 0;
std::unordered_map<InternalPipe*, HostHwPipe*> mPipeToHwPipe;
std::unordered_map<int, FdInfo> mFdInfo;
};
// Initializes a global pipe instance for the current process.
HostGoldfishPipeDevice* getHostPipeInstance();
} // namespace android