IGraphicBufferProducer.cpp 19.3 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
    ALLOW_ALLOCATION,
50
    SET_GENERATION_NUMBER,
51 52
};

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

61 62
    virtual ~BpGraphicBufferProducer();

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

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

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

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

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 162 163
    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;
    }

164 165 166 167 168 169 170 171 172 173 174 175 176
    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;
    }

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

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

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

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

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

    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;
    }
261 262

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

    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;
    }
288 289 290 291 292 293 294 295 296 297 298

    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;
    }
299 300
};

301 302 303 304
// 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
305
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
306 307 308

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

309
status_t BnGraphicBufferProducer::onTransact(
310 311 312 313
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case REQUEST_BUFFER: {
314
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
315
            int bufferIdx   = data.readInt32();
316 317
            sp<GraphicBuffer> buffer;
            int result = requestBuffer(bufferIdx, &buffer);
318 319 320 321
            reply->writeInt32(buffer != 0);
            if (buffer != 0) {
                reply->write(*buffer);
            }
322
            reply->writeInt32(result);
323
            return NO_ERROR;
324
        }
325
        case SET_BUFFER_COUNT: {
326
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
327 328 329 330
            int bufferCount = data.readInt32();
            int result = setBufferCount(bufferCount);
            reply->writeInt32(result);
            return NO_ERROR;
331
        }
332
        case DEQUEUE_BUFFER: {
333
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
334 335 336 337 338
            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();
339
            int buf;
340
            sp<Fence> fence;
341 342
            int result = dequeueBuffer(&buf, &fence, async, width, height,
                    format, usage);
343
            reply->writeInt32(buf);
344 345
            reply->writeInt32(fence != NULL);
            if (fence != NULL) {
346
                reply->write(*fence);
347
            }
348
            reply->writeInt32(result);
349
            return NO_ERROR;
350
        }
351 352 353 354 355 356
        case DETACH_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            int slot = data.readInt32();
            int result = detachBuffer(slot);
            reply->writeInt32(result);
            return NO_ERROR;
357
        }
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
        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;
375
        }
376 377 378 379 380 381 382 383
        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);
384
            return NO_ERROR;
385
        }
386
        case QUEUE_BUFFER: {
387
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
388
            int buf = data.readInt32();
389
            QueueBufferInput input(data);
390 391 392
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
393
            status_t result = queueBuffer(buf, input, output);
394 395
            reply->writeInt32(result);
            return NO_ERROR;
396
        }
397
        case CANCEL_BUFFER: {
398
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
399
            int buf = data.readInt32();
400 401
            sp<Fence> fence = new Fence();
            data.read(*fence.get());
402
            cancelBuffer(buf, fence);
403
            return NO_ERROR;
404
        }
405
        case QUERY: {
406
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
407 408 409 410 411 412
            int value;
            int what = data.readInt32();
            int res = query(what, &value);
            reply->writeInt32(value);
            reply->writeInt32(res);
            return NO_ERROR;
413
        }
414
        case CONNECT: {
415
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
416 417 418 419
            sp<IProducerListener> listener;
            if (data.readInt32() == 1) {
                listener = IProducerListener::asInterface(data.readStrongBinder());
            }
420
            int api = data.readInt32();
421
            bool producerControlledByApp = data.readInt32();
422 423 424
            QueueBufferOutput* const output =
                    reinterpret_cast<QueueBufferOutput *>(
                            reply->writeInplace(sizeof(QueueBufferOutput)));
425
            status_t res = connect(listener, api, producerControlledByApp, output);
426 427
            reply->writeInt32(res);
            return NO_ERROR;
428
        }
429
        case DISCONNECT: {
430
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
431
            int api = data.readInt32();
432
            status_t res = disconnect(api);
433 434
            reply->writeInt32(res);
            return NO_ERROR;
435
        }
436 437 438 439
        case SET_SIDEBAND_STREAM: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            sp<NativeHandle> stream;
            if (data.readInt32()) {
440
                stream = NativeHandle::create(data.readNativeHandle(), true);
441 442 443 444
            }
            status_t result = setSidebandStream(stream);
            reply->writeInt32(result);
            return NO_ERROR;
445
        }
446
        case ALLOCATE_BUFFERS: {
447 448
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            bool async = static_cast<bool>(data.readInt32());
449 450 451 452
            uint32_t width = data.readUint32();
            uint32_t height = data.readUint32();
            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
            uint32_t usage = data.readUint32();
453 454
            allocateBuffers(async, width, height, format, usage);
            return NO_ERROR;
455 456 457 458 459 460 461 462
        }
        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;
        }
463 464 465 466 467 468 469
        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;
        }
470 471 472 473 474 475
    }
    return BBinder::onTransact(code, data, reply, flags);
}

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

476
IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
477 478 479
    parcel.read(*this);
}

Mathias Agopian's avatar
Mathias Agopian committed
480
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
481
    return sizeof(timestamp)
482
         + sizeof(isAutoTimestamp)
483
         + sizeof(dataSpace)
484 485 486
         + sizeof(crop)
         + sizeof(scalingMode)
         + sizeof(transform)
487
         + sizeof(stickyTransform)
488
         + sizeof(async)
489 490
         + fence->getFlattenedSize()
         + surfaceDamage.getFlattenedSize();
491 492
}

Mathias Agopian's avatar
Mathias Agopian committed
493
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
494
    return fence->getFdCount();
495 496
}

Mathias Agopian's avatar
Mathias Agopian committed
497 498
status_t IGraphicBufferProducer::QueueBufferInput::flatten(
        void*& buffer, size_t& size, int*& fds, size_t& count) const
499
{
Mathias Agopian's avatar
Mathias Agopian committed
500 501 502 503
    if (size < getFlattenedSize()) {
        return NO_MEMORY;
    }
    FlattenableUtils::write(buffer, size, timestamp);
504
    FlattenableUtils::write(buffer, size, isAutoTimestamp);
505
    FlattenableUtils::write(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
506 507 508
    FlattenableUtils::write(buffer, size, crop);
    FlattenableUtils::write(buffer, size, scalingMode);
    FlattenableUtils::write(buffer, size, transform);
509
    FlattenableUtils::write(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
510
    FlattenableUtils::write(buffer, size, async);
511 512 513 514 515
    status_t result = fence->flatten(buffer, size, fds, count);
    if (result != NO_ERROR) {
        return result;
    }
    return surfaceDamage.flatten(buffer, size);
516 517
}

Mathias Agopian's avatar
Mathias Agopian committed
518 519
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
        void const*& buffer, size_t& size, int const*& fds, size_t& count)
520
{
Mathias Agopian's avatar
Mathias Agopian committed
521 522
    size_t minNeeded =
              sizeof(timestamp)
523
            + sizeof(isAutoTimestamp)
524
            + sizeof(dataSpace)
Mathias Agopian's avatar
Mathias Agopian committed
525 526 527
            + sizeof(crop)
            + sizeof(scalingMode)
            + sizeof(transform)
528
            + sizeof(stickyTransform)
Mathias Agopian's avatar
Mathias Agopian committed
529 530 531 532 533 534 535
            + sizeof(async);

    if (size < minNeeded) {
        return NO_MEMORY;
    }

    FlattenableUtils::read(buffer, size, timestamp);
536
    FlattenableUtils::read(buffer, size, isAutoTimestamp);
537
    FlattenableUtils::read(buffer, size, dataSpace);
Mathias Agopian's avatar
Mathias Agopian committed
538 539 540
    FlattenableUtils::read(buffer, size, crop);
    FlattenableUtils::read(buffer, size, scalingMode);
    FlattenableUtils::read(buffer, size, transform);
541
    FlattenableUtils::read(buffer, size, stickyTransform);
Mathias Agopian's avatar
Mathias Agopian committed
542 543
    FlattenableUtils::read(buffer, size, async);

544
    fence = new Fence();
545 546 547 548 549
    status_t result = fence->unflatten(buffer, size, fds, count);
    if (result != NO_ERROR) {
        return result;
    }
    return surfaceDamage.unflatten(buffer, size);
550 551
}

552
}; // namespace android