Skip to content

Commit 25d1894

Browse files
feat: HIDL Codec2 encoder via hwbinder, meaningful examples, CI fixes
HIDL C2 listComponents/createComponent/queue working on goldfish. hwparcel FDA/native_handle support (WriteFdArrayObject, WriteEmbeddedNativeHandle). C2Handle format (C2HandleLinearInts, BuildRangeInfoParam). Goldfish gralloc mmap via claimShared + offset. Meaningful codec2_encode example using HIDL path. CreateDisplay test removed (method dropped in API 35).
1 parent c91336c commit 25d1894

7 files changed

Lines changed: 343 additions & 254 deletions

File tree

codec2/hidlcodec2/component.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/binary"
66
"fmt"
7-
"os"
87

98
"github.com/AndroidGoLab/binder/binder"
109
"github.com/AndroidGoLab/binder/hwparcel"
@@ -165,13 +164,6 @@ func (c *Component) Queue(
165164

166165
wb.WriteTo(hp)
167166

168-
// Debug: write to stderr for immediate visibility.
169-
fmt.Fprintf(os.Stderr, "Queue: %d buffers, %d objects, data=%d bytes\n",
170-
hp.BufferCount(), len(hp.ObjectOffsets()), len(hp.DataBytes()))
171-
for _, line := range hp.DumpBufferObjects() {
172-
fmt.Fprintf(os.Stderr, " %s\n", line)
173-
}
174-
175167
reply, err := hwservicemanager.TransactHidl(
176168
ctx, c.transport, c.handle, transactionQueue, hp,
177169
)

codec2/hidlcodec2/param.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,41 @@ func BuildBitrateParam(
5151
return BuildC2Param(index, payload)
5252
}
5353

54+
// BuildRangeInfoParam builds a C2Hal_RangeInfo parameter, which is
55+
// required as the Block.Meta for linear blocks.
56+
//
57+
// C2Hal_RangeInfo is C2GlobalParam<C2Info, C2Hal_Range, 0>.
58+
// Index = KIND_INFO(0xC0000000) | DIR_GLOBAL(0x20000000) | 0 = 0xE0000000.
59+
// Payload: uint32 offset, uint32 length.
60+
func BuildRangeInfoParam(offset uint32, length uint32) []byte {
61+
const rangeInfoIndex = uint32(0xE0000000)
62+
payload := make([]byte, 8)
63+
binary.LittleEndian.PutUint32(payload[0:], offset)
64+
binary.LittleEndian.PutUint32(payload[4:], length)
65+
return BuildC2Param(rangeInfoIndex, payload)
66+
}
67+
68+
// C2HandleIonMagic is the magic value for C2HandleIon / C2HandleBuf.
69+
// Both Ion and DmaBuf allocators use this same magic to identify
70+
// linear block handles.
71+
//
72+
// Computed from the C++ multi-char literal '\xc2io\x00'.
73+
const C2HandleIonMagic = int32(-1033277696) // 0xc2696f00
74+
75+
// C2HandleLinearInts builds the ints array for a C2HandleIon /
76+
// C2HandleBuf native_handle_t. This handle format is recognized by
77+
// the Codec2 framework as a linear block.
78+
//
79+
// The native_handle_t should have numFds=1 (the buffer fd) and
80+
// numInts=3 (sizeLo, sizeHi, magic).
81+
func C2HandleLinearInts(size uint64) []int32 {
82+
return []int32{
83+
int32(size & 0xFFFFFFFF), // sizeLo
84+
int32((size >> 32) & 0xFFFFFFFF), // sizeHi
85+
C2HandleIonMagic, // magic
86+
}
87+
}
88+
5489
// ConcatParams concatenates multiple C2 param blobs into a single
5590
// byte slice, with 8-byte alignment padding between params as required
5691
// by the Codec2 wire format.

codec2/hidlcodec2/work_bundle.go

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ type BaseBlock struct {
3838

3939
// Block references a BaseBlock within a WorkBundle.
4040
type Block struct {
41-
Index uint32
42-
Meta []byte // Params: concatenated C2Param blobs
43-
// Fence is omitted (null handle).
41+
Index uint32
42+
Meta []byte // Params: concatenated C2Param blobs
43+
FenceFds []int32 // Fence native_handle FDs (nil for null fence)
44+
FenceInts []int32 // Fence native_handle ints (nil for null fence)
4445
}
4546

4647
// Buffer is a collection of Blocks with metadata.
@@ -314,10 +315,21 @@ func writeBlocksVec(
314315
// meta data.
315316
writeVecDataChild(hp, blkHandle, baseOff+8, blk.Meta)
316317

317-
// fence: hidl_handle is a nullable pointer. When null (ptr=0),
318-
// no child buffer is written. The HIDL deserializer checks if
319-
// the pointer is non-zero before reading the child buffer.
320-
// We do NOT write an embedded buffer for null handles.
318+
// fence: hidl_handle serialization. The fence is at offset 24
319+
// within each Block struct. The hidl_handle pointer is at
320+
// offset 0 of the hidl_handle struct (= baseOff+24).
321+
//
322+
// For null handles: writeNullNativeHandle writes uint64(0).
323+
// For non-null handles: writeEmbeddedNativeHandle writes
324+
// uint64(size) + PTR buffer + FDA object.
325+
if len(blk.FenceFds) > 0 || len(blk.FenceInts) > 0 {
326+
hp.WriteEmbeddedNativeHandle(
327+
blk.FenceFds, blk.FenceInts,
328+
blkHandle, baseOff+24,
329+
)
330+
} else {
331+
hp.WriteNullNativeHandle()
332+
}
321333
}
322334
}
323335

@@ -408,42 +420,24 @@ func writeBaseBlocksVec(
408420

409421
switch bb.Tag {
410422
case 0: // nativeBlock (hidl_handle)
411-
// hidl_handle data is a native_handle_t.
412-
// The hidl_handle pointer is at baseOff+8.
423+
// hidl_handle serialization. The hidl_handle pointer is
424+
// at baseOff+8 within the BaseBlock struct.
425+
//
426+
// HIDL native_handle serialization requires:
427+
// 1. uint64(size) inline (or uint64(0) if null)
428+
// 2. binder_buffer_object for native_handle_t data
429+
// 3. binder_fd_array_object for FD translation
413430
if len(bb.NativeBlockFds) > 0 || len(bb.NativeBlockInts) > 0 {
414-
nh := marshalNativeHandle(bb.NativeBlockFds, bb.NativeBlockInts)
415-
hp.WriteEmbeddedBuffer(nh, bbHandle, baseOff+8)
431+
hp.WriteEmbeddedNativeHandle(
432+
bb.NativeBlockFds, bb.NativeBlockInts,
433+
bbHandle, baseOff+8,
434+
)
435+
} else {
436+
hp.WriteNullNativeHandle()
416437
}
417-
// Null handle: no child buffer object.
418438
case 1: // pooledBlock
419439
// Not implemented; null pointer, no child.
420440
}
421441
}
422442
}
423443

424-
// marshalNativeHandle builds a native_handle_t blob.
425-
//
426-
// [0:4] int32 version (= sizeof(native_handle_t) = 12)
427-
// [4:8] int32 numFds
428-
// [8:12] int32 numInts
429-
// [12:..] int32[numFds] fds (translated by kernel binder driver)
430-
// [..:] int32[numInts] ints
431-
func marshalNativeHandle(fds, ints []int32) []byte {
432-
size := 12 + len(fds)*4 + len(ints)*4
433-
buf := make([]byte, size)
434-
binary.LittleEndian.PutUint32(buf[0:], 12) // version = sizeof(native_handle_t)
435-
binary.LittleEndian.PutUint32(buf[4:], uint32(len(fds)))
436-
binary.LittleEndian.PutUint32(buf[8:], uint32(len(ints)))
437-
438-
offset := 12
439-
for _, fd := range fds {
440-
binary.LittleEndian.PutUint32(buf[offset:], uint32(fd))
441-
offset += 4
442-
}
443-
for _, v := range ints {
444-
binary.LittleEndian.PutUint32(buf[offset:], uint32(v))
445-
offset += 4
446-
}
447-
448-
return buf
449-
}

0 commit comments

Comments
 (0)