IGraphicBufferProducer.cpp 17.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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>
21
#include <utils/NativeHandle.h>
22 23
#include <utils/RefBase.h>
#include <utils/Timers.h>
24
#include <utils/Vector.h>
25 26 27 28

#include <binder/Parcel.h>
#include <binder/IInterface.h>

29
#include <gui/IGraphicBufferProducer.h>
30
#include <gui/IProducerListener.h>
31 32 33 34 35 36 37 38

namespace android {
// ----------------------------------------------------------------------------

enum {
    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
    SET_BUFFER_COUNT,
    DEQUEUE_BUFFER,
39
    DETACH_BUFFER,
40
    DETACH_NEXT_BUFFER,
41
    ATTACH_BUFFER,
42 43
    QUEUE_BUFFER,
    CANCEL_BUFFER,
44
    QUERY,
45 46
    CONNECT,
    DISCONNECT,
47
    SET_SIDEBAND_STREAM,
48
    ALLOCATE_BUFFERS,
49 50
};

51
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
52 53
{
public:
54 55
    BpGraphicBufferProducer(const sp<IBinder>& impl)
        : BpInterface<IGraphicBufferProducer>(impl)
56 57 58
    {
    }

59 60
    virtual ~BpGraphicBufferProducer();

61
    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
62
        Parcel data, reply;
63
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
64
        data.writeInt32(bufferIdx);
65 66 67 68
        status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
69 70
        bool nonNull = reply.readInt32();
        if (nonNull) {
71
            *buf = new GraphicBuffer();
72 73 74 75 76
            result = reply.read(**buf);
            if(result != NO_ERROR) {
                (*buf).clear();
                return result;
            }
77
        }
78
        result = reply.readInt32();
79
        return result;
80 81 82 83 84
    }

    virtual status_t setBufferCount(int bufferCount)
    {
        Parcel data, reply;
85
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
86
        data.writeInt32(bufferCount);
87 88 89 90 91 92
        status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
        return result;
93 94
    }

95
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
96 97
            uint32_t width, uint32_t height, PixelFormat format,
            uint32_t usage) {
98
        Parcel data, reply;
99
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
100 101 102 103 104
        data.writeInt32(static_cast<int32_t>(async));
        data.writeUint32(width);
        data.writeUint32(height);
        data.writeInt32(static_cast<int32_t>(format));
        data.writeUint32(usage);
105 106 107 108
        status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
109
        *buf = reply.readInt32();
110 111
        bool nonNull = reply.readInt32();
        if (nonNull) {
112
            *fence = new Fence();
113
            reply.read(**fence);
114
        }
115
        result = reply.readInt32();
116 117 118
        return result;
    }

119 120 121 122 123 124 125 126 127 128 129 130
    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;
    }

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
    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;
    }

162 163 164 165 166 167 168 169 170 171 172 173 174
    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();
        return result;
    }

175 176
    virtual status_t queueBuffer(int buf,
            const QueueBufferInput& input, QueueBufferOutput* output) {
177
        Parcel data, reply;
178
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
179
        data.writeInt32(buf);
180
        data.write(input);
181 182 183 184
        status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
185
        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
186
        result = reply.readInt32();
187 188 189
        return result;
    }

190
    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
191
        Parcel data, reply;
192
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
193
        data.writeInt32(buf);
194
        data.write(*fence.get());
195 196 197
        remote()->transact(CANCEL_BUFFER, data, &reply);
    }

198 199
    virtual int query(int what, int* value) {
        Parcel data, reply;
200
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
201
        data.writeInt32(what);
202 203 204 205
        status_t result = remote()->transact(QUERY, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
206
        value[0] = reply.readInt32();
207
        result = reply.readInt32();
208 209 210
        return result;
    }

211
    virtual status_t connect(const sp<IProducerListener>& listener,
212
            int api, bool producerControlledByApp, QueueBufferOutput* output) {
213
        Parcel data, reply;
214
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
215 216
        if (listener != NULL) {
            data.writeInt32(1);
217
            data.writeStrongBinder(IInterface::asBinder(listener));
218 219 220
        } else {
            data.writeInt32(0);
        }
221
        data.writeInt32(api);
222
        data.writeInt32(producerControlledByApp);
223 224 225 226
        status_t result = remote()->transact(CONNECT, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
227
        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
228
        result = reply.readInt32();
229 230
        return result;
    }
231

232 233
    virtual status_t disconnect(int api) {
        Parcel data, reply;
234
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
235
        data.writeInt32(api);
236 237 238 239 240
        status_t result =remote()->transact(DISCONNECT, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
241 242
        return result;
    }
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258

    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;
    }
259 260

    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
261
            PixelFormat format, uint32_t usage) {
262 263 264
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(static_cast<int32_t>(async));
265 266
        data.writeUint32(width);
        data.writeUint32(height);
267
        data.writeInt32(static_cast<int32_t>(format));
268
        data.writeUint32(usage);
269 270 271 272 273
        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
        if (result != NO_ERROR) {
            ALOGE("allocateBuffers failed to transact: %d", result);
        }
    }
274 275
};

276 277 278 279
// Out-of-line virtual method definition to trigger vtable emission in this
// translation unit (see clang warning -Wweak-vtables)
BpGraphicBufferProducer::~BpGraphicBufferProducer() {}

Andy McFadden's avatar
Andy McFadden committed
280
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
281 282 283

// ----------------------------------------------------------------------

284
status_t BnGraphicBufferProducer::onTransact(
285 286 287 288
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case REQUEST_BUFFER: {
289
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
290
            int bufferIdx   = data.readInt32();
291 292
            sp<GraphicBuffer> buffer;
            int result = requestBuffer(bufferIdx, &buffer);
293 294 295 296
            reply->writeInt32(buffer != 0);
            if (buffer != 0) {
                reply->write(*buffer);
            }
297
            reply->writeInt32(result);
298
            return NO_ERROR;
299
        }
300
        case SET_BUFFER_COUNT: {
301
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
302 303 304 305
            int bufferCount = data.readInt32();
            int result = setBufferCount(bufferCount);
            reply->writeInt32(result);
            return NO_ERROR;
306
        }
307
        case DEQUEUE_BUFFER: {
308
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
309 310 311 312 313
            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();
314
            int buf;
315
            sp<Fence> fence;
316 317
            int result = dequeueBuffer(&buf, &fence, async, width, height,
                    format, usage);
318
            reply->writeInt32(buf);
319 320
            reply->writeInt32(fence != NULL);
            if (fence != NULL) {
321
                reply->write(*fence);
322
            }
323
            reply->writeInt32(result);
324
            return NO_ERROR;
325
        }
326 327 328 329 330 331
        case DETACH_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            int slot = data.readInt32();
            int result = detachBuffer(slot);
            reply->writeInt32(result);
            return NO_ERROR;
332
        }
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        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;
350
        }
351 352 353 354 355 356 357 358
        case ATTACH_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            sp<GraphicBuffer> buffer = new GraphicBuffer();
            data.read(*buffer.get());
            int slot;
            int result = attachBuffer(&slot, buffer);
            reply->writeInt32(slot);
            reply->writeInt32(result);
359
            return NO_ERROR;
360
        }
361
        case QUEUE_BUFFER: {
362
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
363
            int buf = data.readInt32();
364
            QueueBufferInput input(data);
365 366 367
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
368
            status_t result = queueBuffer(buf, input, output);
369 370
            reply->writeInt32(result);
            return NO_ERROR;
371
        }
372
        case CANCEL_BUFFER: {
373
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
374
            int buf = data.readInt32();
375 376
            sp<Fence> fence = new Fence();
            data.read(*fence.get());
377
            cancelBuffer(buf, fence);
378
            return NO_ERROR;
379
        }
380
        case QUERY: {
381
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
382 383 384 385 386 387
            int value;
            int what = data.readInt32();
            int res = query(what, &value);
            reply->writeInt32(value);
            reply->writeInt32(res);
            return NO_ERROR;
388
        }
389
        case CONNECT: {
390
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
391 392 393 394
            sp<IProducerListener> listener;
            if (data.readInt32() == 1) {
                listener = IProducerListener::asInterface(data.readStrongBinder());
            }
395
            int api = data.readInt32();
396
            bool producerControlledByApp = data.readInt32();
397 398 399
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
400
            status_t res = connect(listener, api, producerControlledByApp, output);
401 402
            reply->writeInt32(res);
            return NO_ERROR;
403
        }
404
        case DISCONNECT: {
405
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
406
            int api = data.readInt32();
407
            status_t res = disconnect(api);
408 409
            reply->writeInt32(res);
            return NO_ERROR;
410
        }
411 412 413 414
        case SET_SIDEBAND_STREAM: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            sp<NativeHandle> stream;
            if (data.readInt32()) {
415
                stream = NativeHandle::create(data.readNativeHandle(), true);
416 417 418 419
            }
            status_t result = setSidebandStream(stream);
            reply->writeInt32(result);
            return NO_ERROR;
420
        }
421 422 423
        case ALLOCATE_BUFFERS:
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            bool async = static_cast<bool>(data.readInt32());
424 425 426 427
            uint32_t width = data.readUint32();
            uint32_t height = data.readUint32();
            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
            uint32_t usage = data.readUint32();
428 429
            allocateBuffers(async, width, height, format, usage);
            return NO_ERROR;
430 431 432 433 434 435
    }
    return BBinder::onTransact(code, data, reply, flags);
}

// ----------------------------------------------------------------------------

436
IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
437 438 439
    parcel.read(*this);
}

Mathias Agopian's avatar
Mathias Agopian committed
440
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
441
    return sizeof(timestamp)
442
         + sizeof(isAutoTimestamp)
443
         + sizeof(dataSpace)
444 445 446
         + sizeof(crop)
         + sizeof(scalingMode)
         + sizeof(transform)
447
         + sizeof(stickyTransform)
448
         + sizeof(async)
449
         + fence->getFlattenedSize();
450 451
}

Mathias Agopian's avatar
Mathias Agopian committed
452
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
453
    return fence->getFdCount();
454 455
}

Mathias Agopian's avatar
Mathias Agopian committed
456 457
status_t IGraphicBufferProducer::QueueBufferInput::flatten(
        void*& buffer, size_t& size, int*& fds, size_t& count) const
458
{
Mathias Agopian's avatar
Mathias Agopian committed
459 460 461 462
    if (size < getFlattenedSize()) {
        return NO_MEMORY;
    }
    FlattenableUtils::write(buffer, size, timestamp);
463
    FlattenableUtils::write(buffer, size, isAutoTimestamp);
464
    FlattenableUtils::write(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
465 466 467
    FlattenableUtils::write(buffer, size, crop);
    FlattenableUtils::write(buffer, size, scalingMode);
    FlattenableUtils::write(buffer, size, transform);
468
    FlattenableUtils::write(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
469 470
    FlattenableUtils::write(buffer, size, async);
    return fence->flatten(buffer, size, fds, count);
471 472
}

Mathias Agopian's avatar
Mathias Agopian committed
473 474
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
        void const*& buffer, size_t& size, int const*& fds, size_t& count)
475
{
Mathias Agopian's avatar
Mathias Agopian committed
476 477
    size_t minNeeded =
              sizeof(timestamp)
478
            + sizeof(isAutoTimestamp)
479
            + sizeof(dataSpace)
Mathias Agopian's avatar
Mathias Agopian committed
480 481 482
            + sizeof(crop)
            + sizeof(scalingMode)
            + sizeof(transform)
483
            + sizeof(stickyTransform)
Mathias Agopian's avatar
Mathias Agopian committed
484 485 486 487 488 489 490
            + sizeof(async);

    if (size < minNeeded) {
        return NO_MEMORY;
    }

    FlattenableUtils::read(buffer, size, timestamp);
491
    FlattenableUtils::read(buffer, size, isAutoTimestamp);
492
    FlattenableUtils::read(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
493 494 495
    FlattenableUtils::read(buffer, size, crop);
    FlattenableUtils::read(buffer, size, scalingMode);
    FlattenableUtils::read(buffer, size, transform);
496
    FlattenableUtils::read(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
497 498
    FlattenableUtils::read(buffer, size, async);

499
    fence = new Fence();
Mathias Agopian's avatar
Mathias Agopian committed
500
    return fence->unflatten(buffer, size, fds, count);
501 502
}

503
}; // namespace android