123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- /*
- * 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.
- */
- #include <stdint.h>
- #include <sys/types.h>
- #include <utils/Errors.h>
- #include <utils/NativeHandle.h>
- #include <utils/RefBase.h>
- #include <utils/Timers.h>
- #include <utils/Vector.h>
- #include <binder/Parcel.h>
- #include <binder/IInterface.h>
- #include <gui/BufferQueueDefs.h>
- #include <gui/IGraphicBufferProducer.h>
- #include <gui/IProducerListener.h>
- namespace android {
- // ----------------------------------------------------------------------------
- enum {
- REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- SET_BUFFER_COUNT,
- DEQUEUE_BUFFER,
- DETACH_BUFFER,
- DETACH_NEXT_BUFFER,
- ATTACH_BUFFER,
- QUEUE_BUFFER,
- CANCEL_BUFFER,
- QUERY,
- CONNECT,
- DISCONNECT,
- SET_SIDEBAND_STREAM,
- ALLOCATE_BUFFERS,
- ALLOW_ALLOCATION,
- SET_GENERATION_NUMBER,
- GET_CONSUMER_NAME,
- };
- class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
- {
- public:
- BpGraphicBufferProducer(const sp<IBinder>& impl)
- : BpInterface<IGraphicBufferProducer>(impl)
- {
- }
- virtual ~BpGraphicBufferProducer();
- virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(bufferIdx);
- status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- bool nonNull = reply.readInt32();
- if (nonNull) {
- *buf = new GraphicBuffer();
- result = reply.read(**buf);
- if(result != NO_ERROR) {
- (*buf).clear();
- return result;
- }
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t setBufferCount(int bufferCount)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
- uint32_t width, uint32_t height, PixelFormat format,
- uint32_t usage) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(async));
- data.writeUint32(width);
- data.writeUint32(height);
- data.writeInt32(static_cast<int32_t>(format));
- data.writeUint32(usage);
- status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *buf = reply.readInt32();
- bool nonNull = reply.readInt32();
- if (nonNull) {
- *fence = new Fence();
- reply.read(**fence);
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t detachBuffer(int slot) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(slot);
- status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
- if (outBuffer == NULL) {
- ALOGE("detachNextBuffer: outBuffer must not be NULL");
- return BAD_VALUE;
- } else if (outFence == NULL) {
- ALOGE("detachNextBuffer: outFence must not be NULL");
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- if (result == NO_ERROR) {
- bool nonNull = reply.readInt32();
- if (nonNull) {
- *outBuffer = new GraphicBuffer;
- reply.read(**outBuffer);
- }
- nonNull = reply.readInt32();
- if (nonNull) {
- *outFence = new Fence;
- reply.read(**outFence);
- }
- }
- return result;
- }
- virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.write(*buffer.get());
- status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slot = reply.readInt32();
- result = reply.readInt32();
- if (result == NO_ERROR &&
- (*slot < 0 || *slot >= BufferQueueDefs::NUM_BUFFER_SLOTS)) {
- ALOGE("attachBuffer returned invalid slot %d", *slot);
- android_errorWriteLog(0x534e4554, "37478824");
- return UNKNOWN_ERROR;
- }
- return result;
- }
- virtual status_t queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(buf);
- data.write(input);
- status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
- result = reply.readInt32();
- return result;
- }
- virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(buf);
- data.write(*fence.get());
- remote()->transact(CANCEL_BUFFER, data, &reply);
- }
- virtual int query(int what, int* value) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(what);
- status_t result = remote()->transact(QUERY, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- value[0] = reply.readInt32();
- result = reply.readInt32();
- return result;
- }
- virtual status_t connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp, QueueBufferOutput* output) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- if (listener != NULL) {
- data.writeInt32(1);
- data.writeStrongBinder(IInterface::asBinder(listener));
- } else {
- data.writeInt32(0);
- }
- data.writeInt32(api);
- data.writeInt32(producerControlledByApp);
- status_t result = remote()->transact(CONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
- result = reply.readInt32();
- return result;
- }
- virtual status_t disconnect(int api) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(api);
- status_t result =remote()->transact(DISCONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t setSidebandStream(const sp<NativeHandle>& stream) {
- Parcel data, reply;
- status_t result;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- if (stream.get()) {
- data.writeInt32(true);
- data.writeNativeHandle(stream->handle());
- } else {
- data.writeInt32(false);
- }
- if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) {
- result = reply.readInt32();
- }
- return result;
- }
- virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(async));
- data.writeUint32(width);
- data.writeUint32(height);
- data.writeInt32(static_cast<int32_t>(format));
- data.writeUint32(usage);
- status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("allocateBuffers failed to transact: %d", result);
- }
- }
- virtual status_t allowAllocation(bool allow) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(allow));
- status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
- }
- virtual status_t setGenerationNumber(uint32_t generationNumber) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeUint32(generationNumber);
- status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
- if (result == NO_ERROR) {
- result = reply.readInt32();
- }
- return result;
- }
- virtual String8 getConsumerName() const {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("getConsumerName failed to transact: %d", result);
- return String8("TransactFailed");
- }
- return reply.readString8();
- }
- };
- // Out-of-line virtual method definition to trigger vtable emission in this
- // translation unit (see clang warning -Wweak-vtables)
- BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
- IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
- // ----------------------------------------------------------------------
- status_t BnGraphicBufferProducer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- case REQUEST_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int bufferIdx = data.readInt32();
- sp<GraphicBuffer> buffer;
- int result = requestBuffer(bufferIdx, &buffer);
- reply->writeInt32(buffer != 0);
- if (buffer != 0) {
- reply->write(*buffer);
- }
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_BUFFER_COUNT: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int bufferCount = data.readInt32();
- int result = setBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DEQUEUE_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- bool async = static_cast<bool>(data.readInt32());
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- PixelFormat format = static_cast<PixelFormat>(data.readInt32());
- uint32_t usage = data.readUint32();
- int buf = 0;
- sp<Fence> fence;
- int result = dequeueBuffer(&buf, &fence, async, width, height,
- format, usage);
- reply->writeInt32(buf);
- reply->writeInt32(fence != NULL);
- if (fence != NULL) {
- reply->write(*fence);
- }
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DETACH_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int slot = data.readInt32();
- int result = detachBuffer(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DETACH_NEXT_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- sp<GraphicBuffer> buffer;
- sp<Fence> fence;
- int32_t result = detachNextBuffer(&buffer, &fence);
- reply->writeInt32(result);
- if (result == NO_ERROR) {
- reply->writeInt32(buffer != NULL);
- if (buffer != NULL) {
- reply->write(*buffer);
- }
- reply->writeInt32(fence != NULL);
- if (fence != NULL) {
- reply->write(*fence);
- }
- }
- return NO_ERROR;
- }
- case ATTACH_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
- data.read(*buffer.get());
- int slot = 0;
- int result = attachBuffer(&slot, buffer);
- reply->writeInt32(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case QUEUE_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int buf = data.readInt32();
- QueueBufferInput input(data);
- QueueBufferOutput* const output =
- reinterpret_cast<QueueBufferOutput *>(
- reply->writeInplace(sizeof(QueueBufferOutput)));
- memset(output, 0, sizeof(QueueBufferOutput));
- status_t result = queueBuffer(buf, input, output);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case CANCEL_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int buf = data.readInt32();
- sp<Fence> fence = new Fence();
- data.read(*fence.get());
- cancelBuffer(buf, fence);
- return NO_ERROR;
- }
- case QUERY: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int value = 0;
- int what = data.readInt32();
- int res = query(what, &value);
- reply->writeInt32(value);
- reply->writeInt32(res);
- return NO_ERROR;
- }
- case CONNECT: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- sp<IProducerListener> listener;
- if (data.readInt32() == 1) {
- listener = IProducerListener::asInterface(data.readStrongBinder());
- }
- int api = data.readInt32();
- bool producerControlledByApp = data.readInt32();
- QueueBufferOutput* const output =
- reinterpret_cast<QueueBufferOutput *>(
- reply->writeInplace(sizeof(QueueBufferOutput)));
- memset(output, 0, sizeof(QueueBufferOutput));
- status_t res = connect(listener, api, producerControlledByApp, output);
- reply->writeInt32(res);
- return NO_ERROR;
- }
- case DISCONNECT: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int api = data.readInt32();
- status_t res = disconnect(api);
- reply->writeInt32(res);
- return NO_ERROR;
- }
- case SET_SIDEBAND_STREAM: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- sp<NativeHandle> stream;
- if (data.readInt32()) {
- stream = NativeHandle::create(data.readNativeHandle(), true);
- }
- status_t result = setSidebandStream(stream);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case ALLOCATE_BUFFERS: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- bool async = static_cast<bool>(data.readInt32());
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- PixelFormat format = static_cast<PixelFormat>(data.readInt32());
- uint32_t usage = data.readUint32();
- allocateBuffers(async, width, height, format, usage);
- return NO_ERROR;
- }
- case ALLOW_ALLOCATION: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- bool allow = static_cast<bool>(data.readInt32());
- status_t result = allowAllocation(allow);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_GENERATION_NUMBER: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- uint32_t generationNumber = data.readUint32();
- status_t result = setGenerationNumber(generationNumber);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_CONSUMER_NAME: {
- CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- reply->writeString8(getConsumerName());
- return NO_ERROR;
- }
- }
- return BBinder::onTransact(code, data, reply, flags);
- }
- // ----------------------------------------------------------------------------
- IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
- parcel.read(*this);
- }
- size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
- return sizeof(timestamp)
- + sizeof(isAutoTimestamp)
- + sizeof(dataSpace)
- + sizeof(crop)
- + sizeof(scalingMode)
- + sizeof(transform)
- + sizeof(stickyTransform)
- + sizeof(async)
- + fence->getFlattenedSize()
- + surfaceDamage.getFlattenedSize();
- }
- size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
- return fence->getFdCount();
- }
- status_t IGraphicBufferProducer::QueueBufferInput::flatten(
- void*& buffer, size_t& size, int*& fds, size_t& count) const
- {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- FlattenableUtils::write(buffer, size, timestamp);
- FlattenableUtils::write(buffer, size, isAutoTimestamp);
- FlattenableUtils::write(buffer, size, dataSpace);
- FlattenableUtils::write(buffer, size, crop);
- FlattenableUtils::write(buffer, size, scalingMode);
- FlattenableUtils::write(buffer, size, transform);
- FlattenableUtils::write(buffer, size, stickyTransform);
- FlattenableUtils::write(buffer, size, async);
- status_t result = fence->flatten(buffer, size, fds, count);
- if (result != NO_ERROR) {
- return result;
- }
- return surfaceDamage.flatten(buffer, size);
- }
- status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count)
- {
- size_t minNeeded =
- sizeof(timestamp)
- + sizeof(isAutoTimestamp)
- + sizeof(dataSpace)
- + sizeof(crop)
- + sizeof(scalingMode)
- + sizeof(transform)
- + sizeof(stickyTransform)
- + sizeof(async);
- if (size < minNeeded) {
- return NO_MEMORY;
- }
- FlattenableUtils::read(buffer, size, timestamp);
- FlattenableUtils::read(buffer, size, isAutoTimestamp);
- FlattenableUtils::read(buffer, size, dataSpace);
- FlattenableUtils::read(buffer, size, crop);
- FlattenableUtils::read(buffer, size, scalingMode);
- FlattenableUtils::read(buffer, size, transform);
- FlattenableUtils::read(buffer, size, stickyTransform);
- FlattenableUtils::read(buffer, size, async);
- fence = new Fence();
- status_t result = fence->unflatten(buffer, size, fds, count);
- if (result != NO_ERROR) {
- return result;
- }
- return surfaceDamage.unflatten(buffer, size);
- }
- }; // namespace android
|