Merge pull request #7 from monich/hidl_vec
Add gbinder_writer_append_hidl_vec() and gbinder_reader_read_hidl_vec()
This commit is contained in:
		@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -113,6 +113,12 @@ gbinder_reader_read_buffer(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    gsize* elemsize);
 | 
			
		||||
 | 
			
		||||
char*
 | 
			
		||||
gbinder_reader_read_hidl_string(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -121,6 +121,13 @@ gbinder_writer_append_buffer_object(
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize len);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_vec(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize); /* since 1.0.8 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_string(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -305,6 +305,46 @@ gbinder_reader_skip_buffer(
 | 
			
		||||
    return gbinder_reader_read_buffer_impl(reader, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Doesn't copy the data */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    gsize* elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
 | 
			
		||||
    gsize out_count = 0, out_elemsize = 0;
 | 
			
		||||
    const void* out = NULL;
 | 
			
		||||
 | 
			
		||||
    if (buf && buf->size == sizeof(HidlVec)) {
 | 
			
		||||
        const HidlVec* vec = buf->data;
 | 
			
		||||
        const void* next = vec->data.ptr;
 | 
			
		||||
 | 
			
		||||
        if (next) {
 | 
			
		||||
            GBinderBuffer* vbuf = gbinder_reader_read_buffer(reader);
 | 
			
		||||
 | 
			
		||||
            if (vbuf && vbuf->data == next && ((!vec->count && !vbuf->size) ||
 | 
			
		||||
                (vec->count && vbuf->size && !(vbuf->size % vec->count)))) {
 | 
			
		||||
                out_elemsize = vec->count ? (vbuf->size / vec->count) : 0;
 | 
			
		||||
                out_count = vec->count;
 | 
			
		||||
                out = vbuf->data;
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_buffer_free(vbuf);
 | 
			
		||||
        } else if (!vec->count) {
 | 
			
		||||
            /* Any non-NULL pointer just to indicate success */
 | 
			
		||||
            out = vec;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    if (elemsize) {
 | 
			
		||||
        *elemsize = out_elemsize;
 | 
			
		||||
    }
 | 
			
		||||
    if (count) {
 | 
			
		||||
        *count = out_count;
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char*
 | 
			
		||||
gbinder_reader_read_hidl_string(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
 
 | 
			
		||||
@@ -490,6 +490,54 @@ gbinder_writer_append_hidl_string(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_vec(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderParent vec_parent;
 | 
			
		||||
    HidlVec* vec = g_new0(HidlVec, 1);
 | 
			
		||||
    const gsize total = count * elemsize;
 | 
			
		||||
    void* buf = g_memdup(base, total);
 | 
			
		||||
 | 
			
		||||
    /* Prepare parent descriptor for the string data */
 | 
			
		||||
    vec_parent.index = gbinder_writer_data_prepare(data);
 | 
			
		||||
    vec_parent.offset = HIDL_VEC_BUFFER_OFFSET;
 | 
			
		||||
 | 
			
		||||
    /* Fill in the vector descriptor */
 | 
			
		||||
    if (buf) {
 | 
			
		||||
        vec->data.ptr = buf;
 | 
			
		||||
        vec->count = count;
 | 
			
		||||
        data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, buf);
 | 
			
		||||
    }
 | 
			
		||||
    vec->owns_buffer = TRUE;
 | 
			
		||||
    data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec);
 | 
			
		||||
 | 
			
		||||
    /* Write the buffer object pointing to the vector descriptor */
 | 
			
		||||
    gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
 | 
			
		||||
 | 
			
		||||
    /* Not sure what's the right way to deal with NULL vectors... */
 | 
			
		||||
    if (buf) {
 | 
			
		||||
        gbinder_writer_data_write_buffer_object(data, buf, total, &vec_parent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_vec(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriterData* data = gbinder_writer_data(self);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(data)) {
 | 
			
		||||
        gbinder_writer_data_append_hidl_vec(data, base, count, elemsize);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_string(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
 
 | 
			
		||||
@@ -110,6 +110,13 @@ gbinder_writer_data_append_buffer_object(
 | 
			
		||||
    gsize size,
 | 
			
		||||
    const GBinderParent* parent);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_vec(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_string(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
 
 | 
			
		||||
@@ -37,13 +37,17 @@
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "gbinder_remote_object_p.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
typedef struct binder_buffer_object_64 {
 | 
			
		||||
    guint32 type;
 | 
			
		||||
    guint32 flags;
 | 
			
		||||
    guint64 buffer;
 | 
			
		||||
    union {
 | 
			
		||||
        const void* ptr;
 | 
			
		||||
        guint64 value;
 | 
			
		||||
    } buffer;
 | 
			
		||||
    guint64 length;
 | 
			
		||||
    guint64 parent;
 | 
			
		||||
    guint64 parent_offset;
 | 
			
		||||
@@ -51,6 +55,9 @@ typedef struct binder_buffer_object_64 {
 | 
			
		||||
 | 
			
		||||
#define BINDER_TYPE_HANDLE GBINDER_FOURCC('s','h','*',0x85)
 | 
			
		||||
#define BINDER_TYPE_PTR GBINDER_FOURCC('p','t','*',0x85)
 | 
			
		||||
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
 | 
			
		||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
 | 
			
		||||
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * empty
 | 
			
		||||
@@ -62,6 +69,7 @@ test_empty(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    gsize count = 1, elemsize = 1;
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, NULL, 0, 0);
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
@@ -78,6 +86,10 @@ test_empty(
 | 
			
		||||
    g_assert(!gbinder_reader_read_object(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_nullable_object(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_buffer(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
 | 
			
		||||
    g_assert(!count);
 | 
			
		||||
    g_assert(!elemsize);
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_string(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_string_vec(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_skip_buffer(&reader));
 | 
			
		||||
@@ -503,6 +515,216 @@ test_string16(
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_vec
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_hidl_vec {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const void* in;
 | 
			
		||||
    guint in_size;
 | 
			
		||||
    const guint* offset;
 | 
			
		||||
    guint offset_count;
 | 
			
		||||
    const void* data;
 | 
			
		||||
    guint count;
 | 
			
		||||
    guint elemsize;
 | 
			
		||||
} TestHidlVec;
 | 
			
		||||
 | 
			
		||||
static const guint test_hidl_vec_2offsets [] = { 0, BUFFER_OBJECT_SIZE_64 };
 | 
			
		||||
static const guint8 test_hidl_vec_2bytes_data [] = { 0x01, 0x02 };
 | 
			
		||||
static const HidlVec test_hidl_vec_2bytes = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_2bytes_data,
 | 
			
		||||
    sizeof(test_hidl_vec_2bytes_data),
 | 
			
		||||
    TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_2bytes_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_2bytes },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { test_hidl_vec_2bytes_data },
 | 
			
		||||
        sizeof(test_hidl_vec_2bytes_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const HidlVec test_hidl_vec_empty = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_2bytes_data, 0, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_empty_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_empty },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_2bytes_data },
 | 
			
		||||
        0, 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const guint test_hidl_vec_1offset [] = {0};
 | 
			
		||||
static const HidlVec test_hidl_vec_null = {{0}, 0, TRUE};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_null_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_null },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Buffer smaller than HidlVec */
 | 
			
		||||
static const BinderObject64 test_hidl_vec_short_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_empty },
 | 
			
		||||
        sizeof(HidlVec) - 1, 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NULL buffer with size 1 */
 | 
			
		||||
static const guint test_hidl_vec_badnull_offsets [] = {0};
 | 
			
		||||
static const HidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badnull },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Buffer size not divisible by count */
 | 
			
		||||
static const guint8 test_hidl_vec_badsize_data [] = { 0x01, 0x02, 0x03 };
 | 
			
		||||
static const HidlVec test_hidl_vec_badsize = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 2, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badsize_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badsize },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Bad buffer address */
 | 
			
		||||
static const guint8 test_hidl_vec_badbuf_data [] = { 0x01, 0x02, 0x03 };
 | 
			
		||||
static const HidlVec test_hidl_vec_badbuf = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badbuf_data,
 | 
			
		||||
    sizeof(test_hidl_vec_badbuf_data), TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badbuf_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badbuf },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Non-zero count and zero size */
 | 
			
		||||
static const HidlVec test_hidl_vec_badcount1 = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 1, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badcount1_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badcount1 },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        0, 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Zero count0 and non-zero size */
 | 
			
		||||
static const HidlVec test_hidl_vec_badcount2 = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 0, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badcount2_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badcount2 },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const TestHidlVec test_hidl_vec_tests[] = {
 | 
			
		||||
    { "2bytes", TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_data), 1 },
 | 
			
		||||
    { "empty", TEST_ARRAY_AND_SIZE(test_hidl_vec_empty_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
 | 
			
		||||
      test_hidl_vec_2bytes_data, 0, 0 },
 | 
			
		||||
    { "null", TEST_ARRAY_AND_SIZE(test_hidl_vec_null_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset),
 | 
			
		||||
      &test_hidl_vec_null, 0, 0 },
 | 
			
		||||
    { "missingbuf", test_hidl_vec_2bytes_buf,
 | 
			
		||||
      sizeof(test_hidl_vec_2bytes_buf[0]),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "shortbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_short_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "badnull", TEST_ARRAY_AND_SIZE(test_hidl_vec_badnull_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "badsize", TEST_ARRAY_AND_SIZE(test_hidl_vec_badsize_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_badbuf_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badcount1", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount1_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badcount2", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount2_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_hidl_vec(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlVec* test = test_data;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(test->in, test->in_size), test->in_size);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    gsize n = 0, elem = 0;
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = buf;
 | 
			
		||||
    data.reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    if (test->offset) {
 | 
			
		||||
        guint i;
 | 
			
		||||
 | 
			
		||||
        data.objects = g_new(void*, test->offset_count + 1);
 | 
			
		||||
        for (i = 0; i < test->offset_count; i++) {
 | 
			
		||||
            data.objects[i] = (guint8*)buf->data + test->offset[i];
 | 
			
		||||
        }
 | 
			
		||||
        data.objects[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
    g_assert(gbinder_reader_read_hidl_vec(&reader, &n, &elem) == test->data);
 | 
			
		||||
    g_assert(n == test->count);
 | 
			
		||||
    g_assert(elem == test->elemsize);
 | 
			
		||||
 | 
			
		||||
    g_free(data.objects);
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_string_err
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -517,7 +739,7 @@ typedef struct test_hidl_string_err {
 | 
			
		||||
 | 
			
		||||
static const guint8 test_hidl_string_err_short [] = { 0x00 };
 | 
			
		||||
static const guint8 test_hidl_string_err_empty [] = {
 | 
			
		||||
    TEST_INT32_BYTES(GBINDER_FOURCC('p', 't', '*', 0x85)),
 | 
			
		||||
    TEST_INT32_BYTES(BINDER_TYPE_PTR),
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
@@ -693,7 +915,7 @@ test_vec(
 | 
			
		||||
    memset(&vec, 0, sizeof(vec));
 | 
			
		||||
    memset(&obj, 0, sizeof(obj));
 | 
			
		||||
    obj.type = BINDER_TYPE_PTR;
 | 
			
		||||
    obj.buffer = (gsize)&vec;
 | 
			
		||||
    obj.buffer.ptr = &vec;
 | 
			
		||||
 | 
			
		||||
    /* This one will fail because the buffer is one byte short */
 | 
			
		||||
    obj.length = sizeof(vec) - 1;
 | 
			
		||||
@@ -759,6 +981,15 @@ int main(int argc, char* argv[])
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_vec_tests); i++) {
 | 
			
		||||
        const TestHidlVec* test = test_hidl_vec_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "/hidl_vec/", test->name,
 | 
			
		||||
            NULL);
 | 
			
		||||
 | 
			
		||||
        g_test_add_data_func(path, test, test_hidl_vec);
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_string_err_tests); i++) {
 | 
			
		||||
        const TestHidlStringErr* test = test_hidl_string_err_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "/hidl_string/err-", test->name,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -78,6 +78,7 @@ test_null(
 | 
			
		||||
    gbinder_writer_append_bool(&writer, FALSE);
 | 
			
		||||
    gbinder_writer_append_bytes(NULL, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_bytes(&writer, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_hidl_vec(NULL, NULL, 0, 0);
 | 
			
		||||
    gbinder_writer_append_hidl_string(NULL, NULL);
 | 
			
		||||
    gbinder_writer_append_hidl_string(&writer, NULL);
 | 
			
		||||
    gbinder_writer_append_hidl_string_vec(NULL, NULL, 0);
 | 
			
		||||
@@ -339,6 +340,67 @@ test_string16(
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_vec
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_hidl_vec_data {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const GBinderIo* io;
 | 
			
		||||
    const void* data;
 | 
			
		||||
    const gsize count;
 | 
			
		||||
    const gsize elemsize;
 | 
			
		||||
    const guint* offsets;
 | 
			
		||||
    guint offsets_count;
 | 
			
		||||
    guint buffers_size;
 | 
			
		||||
} TestHidlVecData;
 | 
			
		||||
 | 
			
		||||
static guint test_hidl_vec_offsets_0[] =
 | 
			
		||||
    { 0 };
 | 
			
		||||
static guint test_hidl_vec_offsets_32[] =
 | 
			
		||||
    { 0, BUFFER_OBJECT_SIZE_32 };
 | 
			
		||||
static guint test_hidl_vec_offsets_64[] =
 | 
			
		||||
    { 0, BUFFER_OBJECT_SIZE_64 };
 | 
			
		||||
 | 
			
		||||
static const TestHidlVecData test_hidl_vec_tests[] = {
 | 
			
		||||
    { "32/null", &gbinder_io_32, NULL, 0, 0,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_0), sizeof(HidlVec) },
 | 
			
		||||
    { "32/2x1", &gbinder_io_32, "xy", 2, 1,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_32),
 | 
			
		||||
      sizeof(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ },
 | 
			
		||||
    { "64/null", &gbinder_io_64, NULL, 0, 0,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_0), sizeof(HidlVec) },
 | 
			
		||||
    { "64/2x2", &gbinder_io_64, "xxyy", 2, 2,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_64),
 | 
			
		||||
      sizeof(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_hidl_vec(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlVecData* test = test_data;
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(test->io, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_hidl_vec(&writer, test->data,
 | 
			
		||||
        test->count, test->elemsize);
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    g_assert(offsets);
 | 
			
		||||
    g_assert(offsets->count == test->offsets_count);
 | 
			
		||||
    for (i = 0; i < offsets->count; i++) {
 | 
			
		||||
        g_assert(offsets->data[i] == test->offsets[i]);
 | 
			
		||||
    }
 | 
			
		||||
    g_assert(gbinder_output_data_buffers_size(data) == test->buffers_size);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_string
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -649,6 +711,14 @@ int main(int argc, char* argv[])
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_vec_tests); i++) {
 | 
			
		||||
        const TestHidlVecData* test = test_hidl_vec_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "hidl_vec/", test->name, NULL);
 | 
			
		||||
 | 
			
		||||
        g_test_add_data_func(path, test, test_hidl_vec);
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "hidl_string/2strings", test_hidl_string2);
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_string_tests); i++) {
 | 
			
		||||
        const TestHidlStringData* test = test_hidl_string_tests + i;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user