IGraphicBufferProducer.cpp 20.8 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

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

enum {
    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
    DEQUEUE_BUFFER,
38
    DETACH_BUFFER,
39
    DETACH_NEXT_BUFFER,
40
    ATTACH_BUFFER,
41 42
    QUEUE_BUFFER,
    CANCEL_BUFFER,
43
    QUERY,
44 45
    CONNECT,
    DISCONNECT,
46
    SET_SIDEBAND_STREAM,
47
    ALLOCATE_BUFFERS,
48
    ALLOW_ALLOCATION,
49
    SET_GENERATION_NUMBER,
50
    GET_CONSUMER_NAME,
51 52
    SET_MAX_DEQUEUED_BUFFER_COUNT,
    SET_ASYNC_MODE
53 54
};

55
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
56 57
{
public:
58 59
    BpGraphicBufferProducer(const sp<IBinder>& impl)
        : BpInterface<IGraphicBufferProducer>(impl)
60 61 62
    {
    }

63 64
    virtual ~BpGraphicBufferProducer();

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

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
        Parcel data, reply;
        data.writeInterfaceToken(
                IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(maxDequeuedBuffers);
        status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
                data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
        return result;
    }

    virtual status_t setAsyncMode(bool async) {
        Parcel data, reply;
        data.writeInterfaceToken(
                IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(async);
        status_t result = remote()->transact(SET_ASYNC_MODE,
                data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
        return result;
    }

114
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
115 116
            uint32_t width, uint32_t height, PixelFormat format,
            uint32_t usage) {
117
        Parcel data, reply;
118
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
119 120 121 122 123
        data.writeInt32(static_cast<int32_t>(async));
        data.writeUint32(width);
        data.writeUint32(height);
        data.writeInt32(static_cast<int32_t>(format));
        data.writeUint32(usage);
124 125 126 127
        status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
128
        *buf = reply.readInt32();
129 130
        bool nonNull = reply.readInt32();
        if (nonNull) {
131
            *fence = new Fence();
132
            reply.read(**fence);
133
        }
134
        result = reply.readInt32();
135 136 137
        return result;
    }

138 139 140 141 142 143 144 145 146 147 148 149
    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;
    }

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    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;
    }

181 182 183 184 185 186 187 188 189 190 191 192 193
    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;
    }

194 195
    virtual status_t queueBuffer(int buf,
            const QueueBufferInput& input, QueueBufferOutput* output) {
196
        Parcel data, reply;
197
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
198
        data.writeInt32(buf);
199
        data.write(input);
200 201 202 203
        status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
204
        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
205
        result = reply.readInt32();
206 207 208
        return result;
    }

209
    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
210
        Parcel data, reply;
211
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
212
        data.writeInt32(buf);
213
        data.write(*fence.get());
214 215 216
        remote()->transact(CANCEL_BUFFER, data, &reply);
    }

217 218
    virtual int query(int what, int* value) {
        Parcel data, reply;
219
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
220
        data.writeInt32(what);
221 222 223 224
        status_t result = remote()->transact(QUERY, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
225
        value[0] = reply.readInt32();
226
        result = reply.readInt32();
227 228 229
        return result;
    }

230
    virtual status_t connect(const sp<IProducerListener>& listener,
231
            int api, bool producerControlledByApp, QueueBufferOutput* output) {
232
        Parcel data, reply;
233
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
234 235
        if (listener != NULL) {
            data.writeInt32(1);
236
            data.writeStrongBinder(IInterface::asBinder(listener));
237 238 239
        } else {
            data.writeInt32(0);
        }
240
        data.writeInt32(api);
241
        data.writeInt32(producerControlledByApp);
242 243 244 245
        status_t result = remote()->transact(CONNECT, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
246
        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
247
        result = reply.readInt32();
248 249
        return result;
    }
250

251 252
    virtual status_t disconnect(int api) {
        Parcel data, reply;
253
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
254
        data.writeInt32(api);
255 256 257 258 259
        status_t result =remote()->transact(DISCONNECT, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
260 261
        return result;
    }
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

    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;
    }
278 279

    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
280
            PixelFormat format, uint32_t usage) {
281 282 283
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(static_cast<int32_t>(async));
284 285
        data.writeUint32(width);
        data.writeUint32(height);
286
        data.writeInt32(static_cast<int32_t>(format));
287
        data.writeUint32(usage);
288 289 290 291 292
        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
        if (result != NO_ERROR) {
            ALOGE("allocateBuffers failed to transact: %d", result);
        }
    }
293 294 295 296 297 298 299 300 301 302 303 304

    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;
    }
305 306 307 308 309 310 311 312 313 314 315

    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;
    }
316 317 318 319 320 321 322 323 324 325 326

    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();
    }
327 328
};

329 330 331 332
// 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
333
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
334 335 336

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

337
status_t BnGraphicBufferProducer::onTransact(
338 339 340 341
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case REQUEST_BUFFER: {
342
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
343
            int bufferIdx   = data.readInt32();
344 345
            sp<GraphicBuffer> buffer;
            int result = requestBuffer(bufferIdx, &buffer);
346 347 348 349
            reply->writeInt32(buffer != 0);
            if (buffer != 0) {
                reply->write(*buffer);
            }
350
            reply->writeInt32(result);
351
            return NO_ERROR;
352
        }
353 354 355 356 357 358 359 360 361 362 363 364 365 366
        case SET_MAX_DEQUEUED_BUFFER_COUNT: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            int maxDequeuedBuffers = data.readInt32();
            int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case SET_ASYNC_MODE: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            bool async = data.readInt32();
            int result = setAsyncMode(async);
            reply->writeInt32(result);
            return NO_ERROR;
        }
367
        case DEQUEUE_BUFFER: {
368
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
369 370 371 372 373
            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();
374
            int buf;
375
            sp<Fence> fence;
376 377
            int result = dequeueBuffer(&buf, &fence, async, width, height,
                    format, usage);
378
            reply->writeInt32(buf);
379 380
            reply->writeInt32(fence != NULL);
            if (fence != NULL) {
381
                reply->write(*fence);
382
            }
383
            reply->writeInt32(result);
384
            return NO_ERROR;
385
        }
386 387 388 389 390 391
        case DETACH_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            int slot = data.readInt32();
            int result = detachBuffer(slot);
            reply->writeInt32(result);
            return NO_ERROR;
392
        }
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
        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;
410
        }
411 412 413 414 415 416 417 418
        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);
419
            return NO_ERROR;
420
        }
421
        case QUEUE_BUFFER: {
422
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
423
            int buf = data.readInt32();
424
            QueueBufferInput input(data);
425 426 427
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
428
            status_t result = queueBuffer(buf, input, output);
429 430
            reply->writeInt32(result);
            return NO_ERROR;
431
        }
432
        case CANCEL_BUFFER: {
433
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
434
            int buf = data.readInt32();
435 436
            sp<Fence> fence = new Fence();
            data.read(*fence.get());
437
            cancelBuffer(buf, fence);
438
            return NO_ERROR;
439
        }
440
        case QUERY: {
441
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
442 443 444 445 446 447
            int value;
            int what = data.readInt32();
            int res = query(what, &value);
            reply->writeInt32(value);
            reply->writeInt32(res);
            return NO_ERROR;
448
        }
449
        case CONNECT: {
450
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
451 452 453 454
            sp<IProducerListener> listener;
            if (data.readInt32() == 1) {
                listener = IProducerListener::asInterface(data.readStrongBinder());
            }
455
            int api = data.readInt32();
456
            bool producerControlledByApp = data.readInt32();
457 458 459
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
460
            status_t res = connect(listener, api, producerControlledByApp, output);
461 462
            reply->writeInt32(res);
            return NO_ERROR;
463
        }
464
        case DISCONNECT: {
465
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
466
            int api = data.readInt32();
467
            status_t res = disconnect(api);
468 469
            reply->writeInt32(res);
            return NO_ERROR;
470
        }
471 472 473 474
        case SET_SIDEBAND_STREAM: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            sp<NativeHandle> stream;
            if (data.readInt32()) {
475
                stream = NativeHandle::create(data.readNativeHandle(), true);
476 477 478 479
            }
            status_t result = setSidebandStream(stream);
            reply->writeInt32(result);
            return NO_ERROR;
480
        }
481
        case ALLOCATE_BUFFERS: {
482 483
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            bool async = static_cast<bool>(data.readInt32());
484 485 486 487
            uint32_t width = data.readUint32();
            uint32_t height = data.readUint32();
            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
            uint32_t usage = data.readUint32();
488 489
            allocateBuffers(async, width, height, format, usage);
            return NO_ERROR;
490 491 492 493 494 495 496 497
        }
        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;
        }
498 499 500 501 502 503 504
        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;
        }
505 506 507 508 509
        case GET_CONSUMER_NAME: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            reply->writeString8(getConsumerName());
            return NO_ERROR;
        }
510 511 512 513 514 515
    }
    return BBinder::onTransact(code, data, reply, flags);
}

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

516
IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
517 518 519
    parcel.read(*this);
}

Mathias Agopian's avatar
Mathias Agopian committed
520
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
521
    return sizeof(timestamp)
522
         + sizeof(isAutoTimestamp)
523
         + sizeof(dataSpace)
524 525 526
         + sizeof(crop)
         + sizeof(scalingMode)
         + sizeof(transform)
527
         + sizeof(stickyTransform)
528
         + sizeof(async)
529 530
         + fence->getFlattenedSize()
         + surfaceDamage.getFlattenedSize();
531 532
}

Mathias Agopian's avatar
Mathias Agopian committed
533
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
534
    return fence->getFdCount();
535 536
}

Mathias Agopian's avatar
Mathias Agopian committed
537 538
status_t IGraphicBufferProducer::QueueBufferInput::flatten(
        void*& buffer, size_t& size, int*& fds, size_t& count) const
539
{
Mathias Agopian's avatar
Mathias Agopian committed
540 541 542 543
    if (size < getFlattenedSize()) {
        return NO_MEMORY;
    }
    FlattenableUtils::write(buffer, size, timestamp);
544
    FlattenableUtils::write(buffer, size, isAutoTimestamp);
545
    FlattenableUtils::write(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
546 547 548
    FlattenableUtils::write(buffer, size, crop);
    FlattenableUtils::write(buffer, size, scalingMode);
    FlattenableUtils::write(buffer, size, transform);
549
    FlattenableUtils::write(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
550
    FlattenableUtils::write(buffer, size, async);
551 552 553 554 555
    status_t result = fence->flatten(buffer, size, fds, count);
    if (result != NO_ERROR) {
        return result;
    }
    return surfaceDamage.flatten(buffer, size);
556 557
}

Mathias Agopian's avatar
Mathias Agopian committed
558 559
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
        void const*& buffer, size_t& size, int const*& fds, size_t& count)
560
{
Mathias Agopian's avatar
Mathias Agopian committed
561 562
    size_t minNeeded =
              sizeof(timestamp)
563
            + sizeof(isAutoTimestamp)
564
            + sizeof(dataSpace)
Mathias Agopian's avatar
Mathias Agopian committed
565 566 567
            + sizeof(crop)
            + sizeof(scalingMode)
            + sizeof(transform)
568
            + sizeof(stickyTransform)
Mathias Agopian's avatar
Mathias Agopian committed
569 570 571 572 573 574 575
            + sizeof(async);

    if (size < minNeeded) {
        return NO_MEMORY;
    }

    FlattenableUtils::read(buffer, size, timestamp);
576
    FlattenableUtils::read(buffer, size, isAutoTimestamp);
577
    FlattenableUtils::read(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
578 579 580
    FlattenableUtils::read(buffer, size, crop);
    FlattenableUtils::read(buffer, size, scalingMode);
    FlattenableUtils::read(buffer, size, transform);
581
    FlattenableUtils::read(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
582 583
    FlattenableUtils::read(buffer, size, async);

584
    fence = new Fence();
585 586 587 588 589
    status_t result = fence->unflatten(buffer, size, fds, count);
    if (result != NO_ERROR) {
        return result;
    }
    return surfaceDamage.unflatten(buffer, size);
590 591
}

592
}; // namespace android