IGraphicBufferProducer

See IGraphicBufferProducer.cpp and IGraphicBufferProducer HIDL for information about what each transaction's Parcels will look like.

Usage

I'm not particularly familiar with the details of the Android graphics system, but here's how I understand it:

First, you create a window. This gives you an IGraphicBufferProducer. This represents one end of a GraphicBufferQueue, the other being the GraphicBufferConsumer. The consumer side belongs to the surface flinger, which does compositing and gets the image on the screen.

First, you need to CONNECT the IGraphicBufferProducer. The next thing Nintendo code does is preallocates two buffers (instead of letting the BufferQueue talk to gralloc and allocate them itself. I'm not sure why) with SET_PREALLOCATED_BUFFER.

Next, you need to DEQUEUE_BUFFER. This will return you an int32_t slot, which is pretty much a name for a specific buffer. If this is the first time you've seen that slot, you'll have to ask for the details of the buffer with REQUEST_BUFFER.

Once you're done populating the buffer somehow, you QUEUE_BUFFER and DEQEUE_BUFFER again and repeat.

Again, but with dumps.

0xA: CONNECT

request parcel:
parcel+0x0  | 5c 00 00 00 10 00 00 00  00 00 00 00 6c 00 00 00 | \...........l... |
parcel+0x10 | 00 01 00 00 22 00 00 00  61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. |
parcel+0x20 | 6f 00 69 00 64 00 2e 00  67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... |
parcel+0x30 | 49 00 47 00 72 00 61 00  70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. |
parcel+0x40 | 42 00 75 00 66 00 66 00  65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. |
parcel+0x50 | 6f 00 64 00 75 00 63 00  65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... |
parcel+0x60 | 00 00 00 00 02 00 00 00  00 00 00 00             | ............     |
response parcel:
parcel+0x0  | 14 00 00 00 10 00 00 00  00 00 00 00 24 00 00 00 | ............$... |
parcel+0x10 | 00 05 00 00 d0 02 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x20 | 00 00 00 00                                      | ....             |
QueueBufferOutput(width = 1280, height = 720, transformHint = 0, numPendingBuffers = 0)

0xE: PREALLOCATE_BUFFER(0)

preallocate buffer 0
request parcel:
parcel+0x0   | cc 01 00 00 10 00 00 00  00 00 00 00 dc 01 00 00 | ................ |
parcel+0x10  | 00 01 00 00 22 00 00 00  61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. |
parcel+0x20  | 6f 00 69 00 64 00 2e 00  67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... |
parcel+0x30  | 49 00 47 00 72 00 61 00  70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. |
parcel+0x40  | 42 00 75 00 66 00 66 00  65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. |
parcel+0x50  | 6f 00 64 00 75 00 63 00  65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... |
parcel+0x60  | 00 00 00 00 01 00 00 00  6c 01 00 00 00 00 00 00 | ........l....... |
parcel+0x70  | 52 46 42 47 00 05 00 00  d0 02 00 00 00 05 00 00 | RFBG............ |
parcel+0x80  | 01 00 00 00 00 0b 00 00  2a 00 00 00 00 00 00 00 | ........*....... |
parcel+0x90  | 00 00 00 00 51 00 00 00  ff ff ff ff 38 0c 00 00 | ....Q.......8... |
parcel+0xa0  | 00 00 00 00 ff ca ff da  2a 00 00 00 00 00 00 00 | ........*....... |
parcel+0xb0  | 00 0b 00 00 01 00 00 00  01 00 00 00 00 05 00 00 | ................ |
parcel+0xc0  | 00 00 3c 00 01 00 00 00  00 00 00 00 00 05 00 00 | ..<............. |
parcel+0xd0  | d0 02 00 00 20 21 53 00  01 00 00 00 03 00 00 00 | .... !S......... |
parcel+0xe0  | 00 14 00 00 38 0c 00 00  00 00 00 00 fe 00 00 00 | ....8........... |
parcel+0xf0  | 04 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x100 | 00 00 00 00 00 00 3c 00  00 00 00 00 00 00 00 00 | ......<......... |
parcel+0x110 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x120 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x130 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x140 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x150 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x160 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x170 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x180 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x190 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1a0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1b0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1c0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1d0 | 00 00 00 00 e0 39 07 a0  0a 00 00 00             | .....9......     |
response parcel:
parcel+0x0  | 04 00 00 00 10 00 00 00  00 00 00 00 14 00 00 00 | ................ |
parcel+0x10 | 00 00 00 00                                      | ....             |

0xE: PREALLOCATE_BUFFER(1)

preallocate buffer 1
request parcel:
parcel+0x0   | cc 01 00 00 10 00 00 00  00 00 00 00 dc 01 00 00 | ................ |
parcel+0x10  | 00 01 00 00 22 00 00 00  61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. |
parcel+0x20  | 6f 00 69 00 64 00 2e 00  67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... |
parcel+0x30  | 49 00 47 00 72 00 61 00  70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. |
parcel+0x40  | 42 00 75 00 66 00 66 00  65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. |
parcel+0x50  | 6f 00 64 00 75 00 63 00  65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... |
parcel+0x60  | 01 00 00 00 01 00 00 00  6c 01 00 00 00 00 00 00 | ........l....... |
parcel+0x70  | 52 46 42 47 00 05 00 00  d0 02 00 00 00 05 00 00 | RFBG............ |
parcel+0x80  | 01 00 00 00 00 0b 00 00  2a 00 00 00 01 00 00 00 | ........*....... |
parcel+0x90  | 00 00 00 00 51 00 00 00  ff ff ff ff 38 0c 00 00 | ....Q.......8... |
parcel+0xa0  | 00 00 00 00 ff ca ff da  2a 00 00 00 00 00 00 00 | ........*....... |
parcel+0xb0  | 00 0b 00 00 01 00 00 00  01 00 00 00 00 05 00 00 | ................ |
parcel+0xc0  | 00 00 3c 00 01 00 00 00  00 00 00 00 00 05 00 00 | ..<............. |
parcel+0xd0  | d0 02 00 00 20 21 53 00  01 00 00 00 03 00 00 00 | .... !S......... |
parcel+0xe0  | 00 14 00 00 38 0c 00 00  00 00 00 00 fe 00 00 00 | ....8........... |
parcel+0xf0  | 04 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x100 | 00 00 00 00 00 00 3c 00  00 00 00 00 00 00 00 00 | ......<......... |
parcel+0x110 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x120 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x130 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x140 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x150 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x160 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x170 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x180 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x190 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1a0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1b0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1c0 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x1d0 | 00 00 00 00 e0 39 07 a0  0a 00 00 00             | .....9......     |
response parcel:
parcel+0x0  | 04 00 00 00 10 00 00 00  00 00 00 00 14 00 00 00 | ................ |
parcel+0x10 | 00 00 00 00                                      | ....             |

0x3: DEQUEUE_BUFFER

request parcel:
parcel+0x0  | 64 00 00 00 10 00 00 00  00 00 00 00 74 00 00 00 | d...........t... |
parcel+0x10 | 00 01 00 00 22 00 00 00  61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. |
parcel+0x20 | 6f 00 69 00 64 00 2e 00  67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... |
parcel+0x30 | 49 00 47 00 72 00 61 00  70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. |
parcel+0x40 | 42 00 75 00 66 00 66 00  65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. |
parcel+0x50 | 6f 00 64 00 75 00 63 00  65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... |
parcel+0x60 | 01 00 00 00 00 05 00 00  d0 02 00 00 00 00 00 00 | ................ |
parcel+0x70 | 00 03 00 00                                      | ....             |
response parcel:
parcel+0x0  | 38 00 00 00 10 00 00 00  00 00 00 00 48 00 00 00 | 8...........H... |
parcel+0x10 | 00 00 00 00 01 00 00 00  24 00 00 00 00 00 00 00 | ........$....... |
parcel+0x20 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x30 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x40 | 00 00 00 00 00 00 00 00                          | ........         |

0x1: REQUEST_BUFFER

request parcel:
parcel+0x0  | 54 00 00 00 10 00 00 00  00 00 00 00 64 00 00 00 | T...........d... |
parcel+0x10 | 00 01 00 00 22 00 00 00  61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. |
parcel+0x20 | 6f 00 69 00 64 00 2e 00  67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... |
parcel+0x30 | 49 00 47 00 72 00 61 00  70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. |
parcel+0x40 | 42 00 75 00 66 00 66 00  65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. |
parcel+0x50 | 6f 00 64 00 75 00 63 00  65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... |
parcel+0x60 | 00 00 00 00                                      | ....             |
response parcel:
parcel+0x0   | 7c 01 00 00 10 00 00 00  00 00 00 00 8c 01 00 00 | |............... |
parcel+0x10  | 01 00 00 00 6c 01 00 00  00 00 00 00 52 46 42 47 | ....l.......RFBG |
parcel+0x20  | 00 05 00 00 d0 02 00 00  00 05 00 00 01 00 00 00 | ................ |
parcel+0x30  | 00 0b 00 00 2a 00 00 00  00 00 00 00 00 00 00 00 | ....*........... |
parcel+0x40  | 51 00 00 00 ff ff ff ff  38 0c 00 00 00 00 00 00 | Q.......8....... |
parcel+0x50  | ff ca ff da 2a 00 00 00  00 00 00 00 00 0b 00 00 | ....*........... |
parcel+0x60  | 01 00 00 00 01 00 00 00  00 05 00 00 00 00 3c 00 | ..............<. |
parcel+0x70  | 01 00 00 00 00 00 00 00  00 05 00 00 d0 02 00 00 | ................ |
parcel+0x80  | 20 21 53 00 01 00 00 00  03 00 00 00 00 14 00 00 |  !S............. |
parcel+0x90  | 38 0c 00 00 00 00 00 00  fe 00 00 00 04 00 00 00 | 8............... |
parcel+0xa0  | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0xb0  | 00 00 3c 00 00 00 00 00  00 00 00 00 00 00 00 00 | ..<............. |
parcel+0xc0  | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0xd0  | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0xe0  | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0xf0  | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x100 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x110 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x120 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x130 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x140 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x150 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x160 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x170 | 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 | ................ |
parcel+0x180 | 20 67 fa 25 53 00 00 00  00 00 00 00             |  g.%S.......     |

Good Reading

Transaction ID Mapping

0x1: requestBuffer
0x2: setBufferCount
0x3: dequeueBuffer
0x4: detachBuffer
0x5: detachNextBuffer
0x6: attachBuffer
0x7: queueBuffer
0x8: cancelBuffer
0x9: query
0xa: connect
0xb: disconnect
0xc: unknown (setSidebandStream?)
0xd: allocateBuffers
0xe: setPreallocatedBuffer

allocateBuffers>0xD: allocateBuffers

I haven't managed to get this one to work. setPreallocatedBuffer seems to be used instead.

setPreallocatedBuffer>0xE: setPreallocatedBuffer

This one seems to be Nintendo custom. I can't find any reference to it in Android code, but I also haven't looked all that hard. The name is pulled out of some string I found in code related to it.

Here's an example of the Parcel's contents. parcel+0x0 | cc 01 00 00 10 00 00 00 00 00 00 00 dc 01 00 00 | ................ | parcel+0x10 | 00 01 00 00 22 00 00 00 61 00 6e 00 64 00 72 00 | ...."...a.n.d.r. | parcel+0x20 | 6f 00 69 00 64 00 2e 00 67 00 75 00 69 00 2e 00 | o.i.d...g.u.i... | parcel+0x30 | 49 00 47 00 72 00 61 00 70 00 68 00 69 00 63 00 | I.G.r.a.p.h.i.c. | parcel+0x40 | 42 00 75 00 66 00 66 00 65 00 72 00 50 00 72 00 | B.u.f.f.e.r.P.r. | parcel+0x50 | 6f 00 64 00 75 00 63 00 65 00 72 00 00 00 00 00 | o.d.u.c.e.r..... | parcel+0x60 | 00 00 00 00 01 00 00 00 6c 01 00 00 00 00 00 00 | ........l....... | parcel+0x70 | 52 46 42 47 00 05 00 00 d0 02 00 00 00 05 00 00 | RFBG............ | parcel+0x80 | 01 00 00 00 00 0b 00 00 2a 00 00 00 00 00 00 00 | ........*....... | parcel+0x90 | 00 00 00 00 51 00 00 00 ff ff ff ff 30 f3 a4 00 | ....Q.......0... | parcel+0xa0 | 00 00 00 00 ff ca ff da 2a 00 00 00 00 00 00 00 | ........*....... | parcel+0xb0 | 00 0b 00 00 01 00 00 00 01 00 00 00 00 05 00 00 | ................ | parcel+0xc0 | 00 00 3c 00 01 00 00 00 00 00 00 00 00 05 00 00 | ..<............. | parcel+0xd0 | d0 02 00 00 20 21 53 00 01 00 00 00 03 00 00 00 | .... !S......... | parcel+0xe0 | 00 14 00 00 00 00 00 00 00 00 00 00 fe 00 00 00 | ................ | <trimmed> It looks to me like

where AnwBuffer is serialized as a u32 length (0x16c), u32 unknown (0), and then AnwBuffer. I have no idea how the file descriptors get serialized or what all the crud later on is, but vitalk.js has an implementation that works for me.

Data structures

AnwBuffer

See GraphicBuffer.cpp for reference.

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));
}

Flattened Binder Object

typedef struct flat_binder_object
{
    // 8 bytes for large_flat_header.
    unsigned long       type;
    unsigned long       length;

    // 8 bytes of data.
    union {
        void*               binder;     // local object
        signed long         handle;     // remote object
        struct binder_node* node;       // driver node
    };
    void*               cookie;         // extra data associated with local object
} flat_binder_object_t;