blob: ce8d16a5a2ffeb3aac7cda664c8d74708cf15a0e [file] [log] [blame]
// Copyright 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/emulation/testing/TestAndroidPipeDevice.h"
#include "android/emulation/AndroidPipe.h"
#include "android/base/Log.h"
#include <errno.h>
#include <stdint.h>
#include <string.h>
namespace android {
namespace {
class TestGuest : public TestAndroidPipeDevice::Guest {
public:
TestGuest() : mClosed(true), mWakes(0u), mPipe(nullptr) {
mPipe = android_pipe_guest_open(this);
if (!mPipe) {
LOG(ERROR) << "Could not create new "
"TestAndroidPipeDevice::Guest instance!";
}
}
virtual ~TestGuest() { close(); }
virtual int connect(const char* name) override {
std::string handshake("pipe:");
handshake += name;
int len = static_cast<int>(handshake.size()) + 1;
mClosed = false;
int ret = write(handshake.c_str(), len);
if (ret != len) {
LOG(ERROR) << "Could not connect to service " << name
<< " ret=" << ret << " expected len=" << len;
mClosed = true;
return -EINVAL;
}
return 0;
}
virtual ssize_t read(void* buffer, size_t len) override {
if (mClosed) {
return 0;
}
AndroidPipeBuffer buf = { static_cast<uint8_t*>(buffer), len };
return android_pipe_guest_recv(mPipe, &buf, 1);
}
virtual ssize_t write(const void* buffer, size_t len) override {
if (mClosed) {
return 0;
}
AndroidPipeBuffer buf = {
(uint8_t*)buffer, len };
return android_pipe_guest_send(mPipe, &buf, 1);
}
virtual void close() override {
if (!mClosed) {
mClosed = true;
android_pipe_guest_close(mPipe);
}
}
virtual unsigned poll() const override {
if (mClosed) {
return PIPE_POLL_HUP;
}
return android_pipe_guest_poll(mPipe);
}
virtual void* getPipe() const override { return mPipe; }
void resetPipe(void* internal_pipe) {
mPipe = internal_pipe;
}
void closeFromHost() {
mClosed = true;
}
void signalWake(int wakes) {
// NOTE: Update the flags, but for now don't do anything
// about them.
mWakes |= wakes;
}
private:
bool mClosed;
unsigned mWakes;
void* mPipe;
};
} // namespace
TestAndroidPipeDevice::TestAndroidPipeDevice()
: mOldHwFuncs(android_pipe_set_hw_funcs(&sHwFuncs)) {
AndroidPipe::Service::resetAll();
AndroidPipe::initThreading(&mVmLock);
mVmLock.lock();
}
TestAndroidPipeDevice::~TestAndroidPipeDevice() {
android_pipe_set_hw_funcs(mOldHwFuncs);
AndroidPipe::Service::resetAll();
mVmLock.unlock();
}
// static
const AndroidPipeHwFuncs TestAndroidPipeDevice::sHwFuncs = {
&TestAndroidPipeDevice::resetPipe,
&TestAndroidPipeDevice::closeFromHost,
&TestAndroidPipeDevice::signalWake,
};
// static
void TestAndroidPipeDevice::resetPipe(void* hwpipe, void* internal_pipe) {
static_cast<TestGuest*>(hwpipe)->resetPipe(internal_pipe);
}
// static
void TestAndroidPipeDevice::closeFromHost(void* hwpipe) {
static_cast<TestGuest*>(hwpipe)->closeFromHost();
}
// static
void TestAndroidPipeDevice::signalWake(void* hwpipe, unsigned wakes) {
static_cast<TestGuest*>(hwpipe)->signalWake(wakes);
}
// static
TestAndroidPipeDevice::Guest* TestAndroidPipeDevice::Guest::create() {
return new TestGuest();
}
} // namespace android