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
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
|
|
|