remove a dependency of GraphicBuffer (libui) on Parcel (libbinder).

Add a Flattenable interface to libutils which can be used to flatten
an object into bytestream + filedescriptor stream.
Parcel is modified to handle Flattenable. And GraphicBuffer implements
Flattenable.

Except for the overlay classes libui is now independent of libbinder.
This commit is contained in:
Mathias Agopian 2010-02-11 17:30:52 -08:00
parent e4f5055ad2
commit 98e71ddaed
8 changed files with 262 additions and 54 deletions

View File

@ -30,6 +30,7 @@ class IBinder;
class ProcessState;
class String8;
class TextOutput;
class Flattenable;
struct flat_binder_object; // defined in support_p/binder_module.h
@ -81,6 +82,7 @@ public:
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeWeakBinder(const wp<IBinder>& val);
status_t write(const Flattenable& val);
// Place a native_handle into the parcel (the native_handle's file-
// descriptors are dup'ed, so it is safe to delete the native_handle
@ -119,7 +121,7 @@ public:
const char16_t* readString16Inplace(size_t* outLen) const;
sp<IBinder> readStrongBinder() const;
wp<IBinder> readWeakBinder() const;
status_t read(Flattenable& val) const;
// Retrieve native_handle from the parcel. This returns a copy of the
// parcel's native_handle (the caller takes ownership). The caller

View File

@ -23,6 +23,7 @@
#include <ui/android_native_buffer.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <utils/Flattenable.h>
#include <pixelflinger/pixelflinger.h>
struct android_native_buffer_t;
@ -30,7 +31,6 @@ struct android_native_buffer_t;
namespace android {
class GraphicBufferMapper;
class Parcel;
// ===========================================================================
// GraphicBuffer
@ -40,7 +40,7 @@ class GraphicBuffer
: public EGLNativeBase<
android_native_buffer_t,
GraphicBuffer,
LightRefBase<GraphicBuffer> >
LightRefBase<GraphicBuffer> >, public Flattenable
{
public:
@ -97,7 +97,6 @@ public:
uint32_t getVerticalStride() const;
protected:
GraphicBuffer(const Parcel& reply);
virtual ~GraphicBuffer();
enum {
@ -122,8 +121,16 @@ private:
status_t initSize(uint32_t w, uint32_t h, PixelFormat format,
uint32_t usage);
static status_t writeToParcel(Parcel* reply,
android_native_buffer_t const* buffer);
void free_handle();
// Flattenable interface
size_t getFlattenedSize() const;
size_t getFdCount() const;
status_t flatten(void* buffer, size_t size,
int fds[], size_t count) const;
status_t unflatten(void const* buffer, size_t size,
int fds[], size_t count);
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2010 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.
*/
#ifndef ANDROID_UTILS_FLATTENABLE_H
#define ANDROID_UTILS_FLATTENABLE_H
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
namespace android {
class Flattenable
{
public:
// size in bytes of the flattened object
virtual size_t getFlattenedSize() const = 0;
// number of file descriptors to flatten
virtual size_t getFdCount() const = 0;
// flattens the object into buffer.
// size should be at least of getFlattenedSize()
// file descriptors are written in the fds[] array but ownership is
// not transfered (ie: they must be dupped by the caller of
// flatten() if needed).
virtual status_t flatten(void* buffer, size_t size,
int fds[], size_t count) const = 0;
// unflattens the object from buffer.
// size should be equal to the value of getFlattenedSize() when the
// object was flattened.
// unflattened file descriptors are found in the fds[] array and
// don't need to be dupped(). ie: the caller of unflatten doesn't
// keep ownership. If a fd is not retained by unflatten() it must be
// explicitly closed.
virtual status_t unflatten(void const* buffer, size_t size,
int fds[], size_t count) = 0;
protected:
virtual ~Flattenable() = 0;
};
}; // namespace android
#endif /* ANDROID_UTILS_FLATTENABLE_H */

View File

@ -28,6 +28,7 @@
#include <utils/String16.h>
#include <utils/TextOutput.h>
#include <utils/misc.h>
#include <utils/Flattenable.h>
#include <private/binder/binder_module.h>
@ -675,6 +676,42 @@ status_t Parcel::writeDupFileDescriptor(int fd)
return writeObject(obj, true);
}
status_t Parcel::write(const Flattenable& val)
{
status_t err;
// size if needed
size_t len = val.getFlattenedSize();
size_t fd_count = val.getFdCount();
err = this->writeInt32(len);
if (err) return err;
err = this->writeInt32(fd_count);
if (err) return err;
// payload
void* buf = this->writeInplace(PAD_SIZE(len));
if (buf == NULL)
return BAD_VALUE;
int* fds = NULL;
if (fd_count) {
fds = new int[fd_count];
}
err = val.flatten(buf, len, fds, fd_count);
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
err = this->writeDupFileDescriptor( fds[i] );
}
if (fd_count) {
delete [] fds;
}
return err;
}
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
{
const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
@ -713,7 +750,6 @@ restart_write:
goto restart_write;
}
void Parcel::remove(size_t start, size_t amt)
{
LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
@ -940,6 +976,38 @@ int Parcel::readFileDescriptor() const
return BAD_TYPE;
}
status_t Parcel::read(Flattenable& val) const
{
// size
const size_t len = this->readInt32();
const size_t fd_count = this->readInt32();
// payload
void const* buf = this->readInplace(PAD_SIZE(len));
if (buf == NULL)
return BAD_VALUE;
int* fds = NULL;
if (fd_count) {
fds = new int[fd_count];
}
status_t err = NO_ERROR;
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
fds[i] = dup(this->readFileDescriptor());
if (fds[i] < 0) err = BAD_VALUE;
}
if (err == NO_ERROR) {
err = val.unflatten(buf, len, fds, fd_count);
}
if (fd_count) {
delete [] fds;
}
return err;
}
const flat_binder_object* Parcel::readObject(bool nullMetaData) const
{
const size_t DPOS = mDataPos;

View File

@ -78,7 +78,8 @@ public:
data.writeInt32(bufferIdx);
data.writeInt32(usage);
remote()->transact(REQUEST_BUFFER, data, &reply);
sp<GraphicBuffer> buffer = new GraphicBuffer(reply);
sp<GraphicBuffer> buffer = new GraphicBuffer();
reply.read(*buffer);
return buffer;
}
@ -141,7 +142,9 @@ status_t BnSurface::onTransact(
int bufferIdx = data.readInt32();
int usage = data.readInt32();
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
return GraphicBuffer::writeToParcel(reply, buffer.get());
if (buffer == NULL)
return BAD_VALUE;
return reply->write(*buffer);
}
case REGISTER_BUFFERS: {
CHECK_INTERFACE(ISurface, data, reply);

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
#define LOG_TAG "GraphicBuffer"
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@ -77,34 +77,21 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
handle = inHandle;
}
GraphicBuffer::GraphicBuffer(const Parcel& data)
: BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
// we own the handle in this case
width = data.readInt32();
if (width < 0) {
width = height = stride = format = usage = 0;
handle = 0;
} else {
height = data.readInt32();
stride = data.readInt32();
format = data.readInt32();
usage = data.readInt32();
handle = data.readNativeHandle();
}
}
GraphicBuffer::~GraphicBuffer()
{
if (handle) {
if (mOwner == ownHandle) {
native_handle_close(handle);
native_handle_delete(const_cast<native_handle*>(handle));
} else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
free_handle();
}
}
void GraphicBuffer::free_handle()
{
if (mOwner == ownHandle) {
native_handle_close(handle);
native_handle_delete(const_cast<native_handle*>(handle));
} else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
}
@ -192,29 +179,83 @@ status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage)
return res;
}
size_t GraphicBuffer::getFlattenedSize() const {
return (8 + (handle ? handle->numInts : 0))*sizeof(int);
}
status_t GraphicBuffer::writeToParcel(Parcel* reply,
android_native_buffer_t const* buffer)
size_t GraphicBuffer::getFdCount() const {
return handle ? handle->numFds : 0;
}
status_t GraphicBuffer::flatten(void* buffer, size_t size,
int fds[], size_t count) const
{
if (buffer == NULL)
return BAD_VALUE;
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
if (buffer->width < 0 || buffer->height < 0)
return BAD_VALUE;
size_t fdCountNeeded = GraphicBuffer::getFdCount();
if (count < fdCountNeeded) return NO_MEMORY;
status_t err = NO_ERROR;
if (buffer->handle == NULL) {
// this buffer doesn't have a handle
reply->writeInt32(NO_MEMORY);
} else {
reply->writeInt32(buffer->width);
reply->writeInt32(buffer->height);
reply->writeInt32(buffer->stride);
reply->writeInt32(buffer->format);
reply->writeInt32(buffer->usage);
err = reply->writeNativeHandle(buffer->handle);
int* buf = static_cast<int*>(buffer);
buf[0] = 'GBFR';
buf[1] = width;
buf[2] = height;
buf[3] = stride;
buf[4] = format;
buf[5] = usage;
buf[6] = 0;
buf[7] = 0;
if (handle) {
buf[6] = handle->numFds;
buf[7] = handle->numInts;
native_handle_t const* const h = handle;
memcpy(fds, h->data, h->numFds*sizeof(int));
memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
}
return err;
return NO_ERROR;
}
status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
int fds[], size_t count)
{
if (size < 8*sizeof(int)) return NO_MEMORY;
int const* buf = static_cast<int const*>(buffer);
if (buf[0] != 'GBFR') return BAD_TYPE;
const size_t numFds = buf[6];
const size_t numInts = buf[7];
const size_t sizeNeeded = (8 + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
size_t fdCountNeeded = 0;
if (count < fdCountNeeded) return NO_MEMORY;
if (handle) {
// free previous handle if any
free_handle();
}
if (numFds || numInts) {
width = buf[1];
height = buf[2];
stride = buf[3];
format = buf[4];
usage = buf[5];
native_handle* h = native_handle_create(numFds, numInts);
memcpy(h->data, fds, numFds*sizeof(int));
memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));
handle = h;
} else {
width = height = stride = format = usage = 0;
handle = NULL;
}
mOwner = ownHandle;
return NO_ERROR;
}

View File

@ -25,6 +25,7 @@ commonSources:= \
CallStack.cpp \
Debug.cpp \
FileMap.cpp \
Flattenable.cpp \
RefBase.cpp \
ResourceTypes.cpp \
SharedBuffer.cpp \

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2006 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.
*/
#include <utils/Flattenable.h>
namespace android {
Flattenable::~Flattenable() {
}
}; // namespace android