blob: 3b03f6ba4ad5e714eb7f50344aceb6b811d0a27d [file] [log] [blame]
// Copyright 2018 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 "RefcountPipe.h"
#include "base/ArraySize.h"
#include "refcount-pipe.h"
using android::base::arraySize;
namespace android {
namespace emulation {
static OnLastColorBufferRef* sOnLastColorBufferRef = nullptr;
RefcountPipe::RefcountPipe(void* hwPipe, Service* svc, base::Stream* loadStream)
: AndroidPipe(hwPipe, svc) {
if (loadStream) {
mHandle = loadStream->getBe32();
} else {
mHandle = 0;
}
}
RefcountPipe::~RefcountPipe() {
OnLastColorBufferRef func = *sOnLastColorBufferRef;
if (func != nullptr)
func(mHandle);
}
void RefcountPipe::onGuestClose(PipeCloseReason reason) {
delete this;
}
unsigned RefcountPipe::onGuestPoll() const {
// Guest can always write
return PIPE_POLL_OUT;
}
int RefcountPipe::onGuestRecv(AndroidPipeBuffer* buffers, int numBuffers) {
// Guest is not supposed to read
return PIPE_ERROR_IO;
}
int RefcountPipe::onGuestSend(const AndroidPipeBuffer* buffers,
int numBuffers,
void** newPipePtr) {
int result = 0;
char forRecv[4] = {};
while (numBuffers > 0 && arraySize(forRecv) - result >= buffers->size) {
memcpy(forRecv + result, buffers->data, buffers->size);
result += static_cast<int>(buffers->size);
buffers++;
numBuffers--;
}
if (result == arraySize(forRecv)) {
memcpy(&mHandle, forRecv, arraySize(forRecv));
}
return result;
}
void RefcountPipe::onSave(base::Stream* stream) {
stream->putBe32(mHandle);
}
void registerRefcountPipeService() {
AndroidPipe::Service::add(std::make_unique<RefcountPipe::Service>());
}
////////////////////////////////////////////////////////////////////////////////
RefcountPipe::Service::Service() : AndroidPipe::Service("refcount") {}
AndroidPipe* RefcountPipe::Service::create(void* hwPipe, const char* args) {
return new RefcountPipe(hwPipe, this);
}
AndroidPipe* RefcountPipe::Service::load(void* hwPipe,
const char* args,
android::base::Stream* stream) {
return new RefcountPipe(hwPipe, this, stream);
}
bool RefcountPipe::Service::canLoad() const {
return true;
}
void registerOnLastRefCallback(OnLastColorBufferRef func) {
*sOnLastColorBufferRef = func;
}
} // namespace emulation
} // namespace android
void android_init_refcount_pipe(void) {
android::emulation::registerRefcountPipeService();
}