Compare commits

...

39 Commits

Author SHA1 Message Date
Slava Monich
d3bc7bb63b Version 1.1.42 2024-12-11 06:40:35 +02:00
Slava Monich
f525378b18 Merge pull request #133 from peat-psuwit/for-upstream/libgbinder-stability-android-rs
Correct stability field wire format on Android 12
2024-12-10 18:47:26 +02:00
Slava Monich
43676db1b9 Merge pull request #141 from monich/sm_remove_handlers
Make coverity happy
2024-12-10 11:19:07 +02:00
Slava Monich
18c4f24fd3 Merge pull request #140 from monich/async_watch
Register for sm notifications asynchronously
2024-11-25 16:56:19 +02:00
Slava Monich
4cc22d8256 [gbinder] Delete name watches with no handlers. SX#GULBI-122
There's no need to keep the watch around if no one is listening
for its signals.

This also makes coverity happier. It was complaining about the
'disconnected' variable which wasn't really necessary because
there isn't much to optimize here.
2024-11-24 06:40:34 +02:00
Slava Monich
c836a7da81 [gbinder] Register for sm notifications asynchronously. SX#APPSUPPORT-189
To avoid deadlocks.
2024-11-24 03:15:01 +02:00
Slava Monich
2446d39d4b [unit] Fixed compilation warning
unit_writer.c: In function 'test_local_object':
unit_writer.c:1353:20: warning: unused variable 'offsets' [-Wunused-variable]
 1353 |     GUtilIntArray* offsets;
      |                    ^~~~~~~
2024-11-24 02:44:33 +02:00
Slava Monich
d3233ac89f [gbinder] Removed duplicate typedef
GBinderServiceManager is defined in gbinder_types.h
2024-11-19 02:08:38 +02:00
Slava Monich
ba9fff8a06 Version 1.1.41
[gbinder] JB#42956
2024-11-02 05:14:34 +02:00
Slava Monich
311756ae11 Acknowledge Ratchanan's contribution 2024-10-28 02:46:34 +02:00
Slava Monich
98459e4053 Merge pull request #135 from peat-psuwit/for-upstream/encode-null-binder
Fix sending NULL binder object
2024-10-28 02:44:04 +02:00
Ratchanan Srirattanamet
374526be9c [gbinder] uses aidl3 servicemanager on API level 31 & 32
Nikita (@NotKit) noticed that the change in commit f227ae4291
("[gbinder] All binder objects need stability field in Android 11.
JB#58951") has made the aidl4 servicemanager variant redundant. In fact,
using aidl4 variant will cause an extra stability field to be sent on
the wire (luckily it has not caused any problem).

I've tried using aidl3 variant on Volla Phone X23 which runs Halium 12
(API level 32), and service registration still work, which seems to
validate this theory. Thus, stop using aidl4 servicemanager variant on
any of the API level-based config, as it no longer correspond to any of
Android versions.

Note that this commit doesn't outright remove aidl4 variant, as doing so
would break configurations which explicitly request its use. This commit
doesn't doesn't alias the aidl4 variant to aidl3 variant either.
Manually requesting a certain variant could mean some unusual setup;
aliasing aidl4 to aidl3 could break such setup.
2024-10-13 03:16:10 +07:00
Ratchanan Srirattanamet
62dac7e893 [gbinder] correct stability field wire format on Android 12
On Android 12, the wire format of stability field is changed to also
include so-called "Binder wire format version", which starts at 1 [1].
A 32-bit-sized struct is re-interpreted into a 32-bit integer, with a
layout which makes it incompatible with the old version. Interestingly,
they reverted this idea in Android 13 [2], which makes the wire format
of the stability field the same as Android 11 again (as far as I know).

Add a new RPC protocol variant 'aidl4' to account for this difference.
Use this protocol on API level 31 through 32 and use 'aidl3' from API
level 33 onwards. The only difference from 'aidl3' is `finish_flatten_
binder()` function.

Interestingly, there is also a 16-bit-sized struct variant of the field
too [3]. However, to the best of my knowledge, this version is not used
in any of the released Android versions.

[1]: 89ddfc5f8c
[2]: 16a4106cb7
[3]: 14e4cfae36
2024-10-13 03:16:01 +07:00
Ratchanan Srirattanamet
aa946b4c31 [gbinder] writer: don't write object offset for NULL binder object
Writing offset will trigger the kernel-side code to transform the flat
binder object into the handle form, which (in my understanding) is not
a valid operation for a NULL binder object. Meanwhile, the receiving
side will create a corresponding Binder object from such handle,
tripping the stability check as it will no longer accept UNDECLARED.

OTOH, if the offset is not written, then the receiving side will receive
the flat binder object as-is, with type BINDER and pointer NULL, which
will be interpreted as NULL binder. This is also what Android's
Parcel.cpp does [1][2].

IMO, this is sort of a hack. Binder kernel driver should handle the NULL
binder internally, and not relying on the sender doing the correct
thing. Meanwhile, the receiver should always reject a flat binder object
of type BINDER. But that's how Android work, so... 🤷

[1]: https://github.com/LineageOS/android_frameworks_native/blob/lineage-19.1/libs/binder/Parcel.cpp#L1327-L1332
[2]: https://github.com/LineageOS/android_frameworks_native/blob/lineage-19.1/libs/binder/Parcel.cpp#L2023-L2029
2024-10-05 21:05:37 +07:00
Ratchanan Srirattanamet
b81f35d1ff [gbinder] use BINDER_TYPE_BINDER for NULL local object
3 reasons:
- This is what encode_remote_object() does. I see no reason a NULL local
  object should be encoded differently than a NULL remote object.
- This is what Parcel.cpp does when flattening a NULL binder [1]. This
  is contrary to what is said in PR #99 [2]; I'm not sure why PR #99
  said it uses BINDER_TYPE_HANDLE.
- More importantly, BINDER_TYPE_HANDLE number 0 does NOT represent a
  NULL binder. According to the comment at [3], handle number 0 actually
  represent the context manager. So, by sending BINDER_TYPE_HANDLE
  number 0, we're sending context manager, not a NULL binder.

[1]: https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-14.0.0_r1/libs/binder/Parcel.cpp#277
[2]: https://github.com/mer-hybris/libgbinder/pull/99
[3]: https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-14.0.0_r1/libs/binder/ProcessState.cpp#336
2024-10-02 23:46:31 +07:00
Slava Monich
c35d266c77 Merge pull request #134 from monich/read_string8
Add gbinder_reader_read_nullable_string8
2024-09-25 14:06:15 +03:00
Slava Monich
3350f51a21 [gbinder] Added gbinder_reader_read_nullable_string8
The equivalent of Android's Parcel::readString8
2024-09-24 18:48:39 +03:00
Slava Monich
5cfe96b891 [gbinder] Check if counted strings are NULL-terminated
That's what Parcel::readString16 does.
2024-09-24 18:35:02 +03:00
Slava Monich
20774aecac [unit] Improved gbinder_reader test coverage 2024-09-24 17:02:07 +03:00
Slava Monich
624bfa843d Version 1.1.40 2024-07-18 05:35:00 +03:00
Slava Monich
6d71a0649c [gbinder] Housekeeping 2024-07-18 05:32:36 +03:00
Slava Monich
c31cd7e964 Acknowledge Nikita's contribution 2024-07-18 05:08:47 +03:00
Slava Monich
c1db86e734 Merge pull request #130 from mer-hybris/aidl-stability
Make stability field of local object configurable
2024-07-18 05:04:50 +03:00
Nikita Ukhrenkov
bfb95f2bf5 [gbinder] Make stability field of local object configurable. JB#61912
AIDL HALs require stability field value to be set to VINTF as
opposed to the default SYSTEM, so expose a way to let the caller
set the value to used by finish_flatten_binder per local object.
2024-07-15 18:42:20 +03:00
Slava Monich
6f4c69d58a Merge pull request #131 from monich/unit_conf
Make more unit tests independent on system config
2024-07-15 17:29:17 +03:00
Slava Monich
c6b09a10d4 [unit] Make more unit tests independent on system config. JB#42956
System gbinder config shouldn't break unit tests.
2024-07-14 06:15:19 +03:00
Slava Monich
545f5bc28d Version 1.1.39 2024-05-05 20:09:11 +03:00
Slava Monich
78e006f1cf Acknowledge Martin's contribution 2024-05-05 20:08:23 +03:00
Slava Monich
3c9cc1711a [spec] Cleaned up macro syntax 2024-04-30 20:25:43 +03:00
Slava Monich
71aa3acc08 [spec] Restore compatibility with rpm < 4.12 (again) 2024-04-30 02:42:25 +03:00
Slava Monich
eee26c5e98 [spec] Restore compatibility with rpm < 4.12 2024-04-30 02:18:18 +03:00
Slava Monich
736a29aa4c Merge pull request #128 from mer-hybris/jb61933
Utilize make_build macro
2024-04-29 19:54:51 +03:00
Martin Kampas
0d7105edbe [gbinder] Utilize make_build macro. JB#61933
Allow the build system to override the way make is invoked.

Cannot use make_install equally as that does not allow to pass
additional arguments to make.
2024-04-16 13:36:50 +02:00
Slava Monich
4420c7b2ae Merge pull request #126 from mer-hybris/jb61912
Eliminate defects found by Coverity
2024-04-12 04:51:00 +03:00
Martin Kampas
52726a07b0 [gbinder] Add model file for Coverity. JB#61912
Eliminate false positive. Help Coverity see there is no resource leak
(CID 444479).
2024-04-11 12:59:39 +02:00
Martin Kampas
12b9fd49ad [gbinder] Avoid double-checked locking in gbinder_ipc_looper_check. JB#61912
Data race condition detected by Coverity (CID 444481, CID 444483).

According to Slava the effect of this particular optimization is
negligible, so let's simply drop it to make Coverity happy.
2024-04-11 12:57:13 +02:00
Martin Kampas
e75959e389 [gbinder] Explicitly ignore return value. JB#61912
Recognized by Coverity (CID 444485) that this is the single call to
gbinder_driver_write out of the total of 9, where the return value is
not checked.

This change is implemented just to make Coverity happy.  The compiler
does not complain.
2024-04-11 12:45:33 +02:00
Slava Monich
9d35ca22fb Merge pull request #127 from monich/set_data
Remove unnecessary checks for NULL
2024-04-11 13:09:34 +03:00
Slava Monich
3e0d0005ce [gbinder] Remove unnecessary checks for NULL. JB#61912
And fix potential use after free.
2024-04-11 03:29:28 +03:00
34 changed files with 675 additions and 244 deletions

View File

@@ -1,4 +1,4 @@
Slava Monich <slava.monich@jolla.com>
Slava Monich <slava@monich.com>
Matti Lehtimäki <matti.lehtimaki@gmail.com>
Franz-Josef Haider <franz.haider@jolla.com>
Juho Hämäläinen <juho.hamalainen@jolla.com>
@@ -9,3 +9,6 @@ Bart Ribbers <bribbers@disroot.org>
Gary Wang <gary.wang@canonical.com>
Eugenio Paolantonio <me@medesimo.eu>
Alessandro Astone <ales.astone@gmail.com>
Martin Kampas <martin.kampas@seafarix.com>
Nikita Ukhrenkov <nikita.ukhrenkov@seafarix.com>
Ratchanan Srirattanamet <ratchanan@ubports.com>

View File

@@ -16,7 +16,7 @@
VERSION_MAJOR = 1
VERSION_MINOR = 1
VERSION_RELEASE = 38
VERSION_RELEASE = 42
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)

30
debian/changelog vendored
View File

@@ -1,3 +1,33 @@
libgbinder (1.1.42) unstable; urgency=low
* Delete name watches with no handlers
* Register for sm notifications asynchronously
* Correct stability field wire format on Android 12
-- Slava Monich <slava@monich.com> Wed, 11 Dec 2024 06:40:00 +0200
libgbinder (1.1.41) unstable; urgency=low
* Fix sending NULL binder object
* Added gbinder_reader_read_nullable_string8
* Check if counted strings are NULL-terminated
-- Slava Monich <slava@monich.com> Sat, 02 Nov 2024 05:13:22 +0200
libgbinder (1.1.40) unstable; urgency=low
* Make stability field of local object configurable
* Make more unit tests independent on system config
* Use UNDECLARED stability for NULL binders
-- Slava Monich <slava@monich.com> Thu, 18 Jul 2024 05:14:28 +0300
libgbinder (1.1.39) unstable; urgency=low
* Eliminate defects found by Coverity
-- Slava Monich <slava@monich.com> Sun, 05 May 2024 20:03:44 +0300
libgbinder (1.1.38) unstable; urgency=low
* Fixed byte array padding

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -61,6 +61,11 @@ GBinderLocalReply*
gbinder_local_object_new_reply(
GBinderLocalObject* obj);
void
gbinder_local_object_set_stability(
GBinderLocalObject* self,
GBINDER_STABILITY_LEVEL stability); /* Since 1.1.40 */
G_END_DECLS
#endif /* GBINDER_LOCAL_OBJECT_H */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -196,6 +196,15 @@ const char*
gbinder_reader_read_string8(
GBinderReader* reader);
gboolean
gbinder_reader_read_nullable_string8(
GBinderReader* reader,
const char** out,
gsize* out_len); /* Since 1.1.41 */
#define gbinder_reader_skip_nullable_string8(reader) \
gbinder_reader_read_nullable_string8(reader, NULL, NULL)
char*
gbinder_reader_read_string16(
GBinderReader* reader)

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -173,6 +173,13 @@ typedef enum gbinder_status {
GBINDER_STATUS_DEAD_OBJECT
} GBINDER_STATUS;
typedef enum gbinder_stability_level {
GBINDER_STABILITY_UNDECLARED = 0,
GBINDER_STABILITY_VENDOR = 0x03,
GBINDER_STABILITY_SYSTEM = 0x0c,
GBINDER_STABILITY_VINTF = 0x3f
} GBINDER_STABILITY_LEVEL; /* Since 1.1.40 */
#define GBINDER_FOURCC(c1,c2,c3,c4) \
(((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))

8
misc/coverity_model.c Normal file
View File

@@ -0,0 +1,8 @@
typedef struct gbinder_remote_request GBinderRemoteRequest;
void
gbinder_remote_request_unref(
GBinderRemoteRequest* req)
{
__coverity_free__(req);
}

View File

@@ -1,6 +1,6 @@
Name: libgbinder
Version: 1.1.38
Version: 1.1.42
Release: 0
Summary: Binder client library
License: BSD
@@ -20,6 +20,9 @@ BuildRequires: flex
BuildRequires: pkgconfig(rpm)
%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
# make_build macro appeared in rpm 4.12
%{!?make_build:%define make_build make %{_smp_mflags}}
Requires: glib2 >= %{glib_version}
Requires: libglibutil >= %{libglibutil_version}
Requires(post): /sbin/ldconfig
@@ -40,11 +43,11 @@ This package contains the development library for %{name}.
%setup -q
%build
make %{_smp_mflags} LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
make -C test/binder-bridge KEEP_SYMBOLS=1 release
make -C test/binder-list KEEP_SYMBOLS=1 release
make -C test/binder-ping KEEP_SYMBOLS=1 release
make -C test/binder-call KEEP_SYMBOLS=1 release
%make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
%make_build -C test/binder-bridge -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-list -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-ping -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-call -j1 KEEP_SYMBOLS=1 release
%install
make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev

View File

@@ -135,21 +135,30 @@ static const GBinderConfigPresetGroup gbinder_config_30[] = {
/* API level 31 */
static const GBinderConfigPresetEntry gbinder_config_31_servicemanager[] = {
static const GBinderConfigPresetEntry gbinder_config_31_protocol[] = {
{ "/dev/binder", "aidl4" },
{ "/dev/vndbinder", "aidl4" },
{ NULL, NULL }
};
static const GBinderConfigPresetGroup gbinder_config_31[] = {
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_31_protocol },
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
{ NULL, NULL }
};
/* API level 33 - reverts back to AIDL3 protocol */
static const GBinderConfigPresetGroup gbinder_config_33[] = {
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_31_servicemanager },
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
{ NULL, NULL }
};
/* Presets sorted by API level in descending order */
static const GBinderConfigPreset gbinder_config_presets[] = {
{ 33, gbinder_config_33 },
{ 31, gbinder_config_31 },
{ 30, gbinder_config_30 },
{ 29, gbinder_config_29 },

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -813,7 +813,7 @@ gbinder_driver_txstatus(
gbinder_driver_verbose_transaction_data("BR_REPLY", &tx);
/* Transfer data ownership to the reply */
if (tx.data && tx.size) {
if (tx.data && tx.size && reply) {
GBinderBuffer* buf = gbinder_buffer_new(self,
tx.data, tx.size, tx.objects);
@@ -1173,7 +1173,7 @@ gbinder_driver_free_buffer(
write.ptr = (uintptr_t)wbuf;
write.size = len;
write.consumed = 0;
gbinder_driver_write(self, &write);
(void) gbinder_driver_write(self, &write);
}
}

View File

@@ -175,12 +175,10 @@ GBINDER_IO_FN(encode_local_object)(
struct flat_binder_object* dest = out;
memset(dest, 0, sizeof(*dest));
dest->hdr.type = BINDER_TYPE_BINDER;
if (obj) {
dest->hdr.type = BINDER_TYPE_BINDER;
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
dest->binder = (uintptr_t)obj;
} else {
dest->hdr.type = BINDER_TYPE_HANDLE;
}
if (protocol->finish_flatten_binder) {
protocol->finish_flatten_binder(dest + 1, obj);

View File

@@ -905,28 +905,25 @@ gbinder_ipc_looper_check(
{
if (G_LIKELY(self)) {
GBinderIpcPriv* priv = self->priv;
GBinderIpcLooper* new_looper = NULL;
/* Lock */
g_mutex_lock(&priv->looper_mutex);
if (!priv->primary_loopers) {
GBinderIpcLooper* looper;
priv->primary_loopers = gbinder_ipc_looper_new(self);
new_looper = priv->primary_loopers;
if (new_looper) {
gbinder_ipc_looper_ref(new_looper);
}
}
g_mutex_unlock(&priv->looper_mutex);
/* Unlock */
/* Lock */
g_mutex_lock(&priv->looper_mutex);
if (!priv->primary_loopers) {
priv->primary_loopers = gbinder_ipc_looper_new(self);
}
looper = priv->primary_loopers;
if (looper) {
gbinder_ipc_looper_ref(looper);
}
g_mutex_unlock(&priv->looper_mutex);
/* Unlock */
/* We are not ready to accept incoming transactions until
* looper has started. We may need to wait a bit. */
if (looper) {
gbinder_ipc_looper_start(looper);
gbinder_ipc_looper_unref(looper);
}
/* We are not ready to accept incoming transactions until
* looper has started. We may need to wait a bit. */
if (new_looper) {
gbinder_ipc_looper_start(new_looper);
gbinder_ipc_looper_unref(new_looper);
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -442,6 +442,7 @@ gbinder_local_object_init_base(
self->ipc = gbinder_ipc_ref(ipc);
self->ifaces = (const char**)priv->ifaces;
self->stability = GBINDER_STABILITY_SYSTEM;
priv->txproc = txproc;
priv->user_data = user_data;
}
@@ -611,6 +612,16 @@ gbinder_local_object_handle_release(
gbinder_local_object_handle_later(self, gbinder_local_object_release_proc);
}
void
gbinder_local_object_set_stability(
GBinderLocalObject* self,
GBINDER_STABILITY_LEVEL stability) /* Since 1.1.40 */
{
if (G_LIKELY(self)) {
self->stability = stability;
}
}
/*==========================================================================*
* Internals
*==========================================================================*/

View File

@@ -59,6 +59,7 @@ struct gbinder_local_object {
const char* const* ifaces;
gint weak_refs;
gint strong_refs;
GBINDER_STABILITY_LEVEL stability;
};
typedef enum gbinder_local_transaction_support {

View File

@@ -617,6 +617,7 @@ gbinder_reader_read_hidl_string_vec(
return NULL;
}
/* The equivalent of Android's Parcel::readCString */
const char*
gbinder_reader_read_string8(
GBinderReader* reader)
@@ -641,6 +642,49 @@ gbinder_reader_read_string8(
return NULL;
}
/* The equivalent of Android's Parcel::readString8 */
gboolean
gbinder_reader_read_nullable_string8(
GBinderReader* reader,
const char** out,
gsize* out_len) /* Since 1.1.41 */
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if ((p->ptr + 4) <= p->end) {
const gint32* len_ptr = (gint32*)p->ptr;
const gint32 len = *len_ptr;
if (len == -1) {
/* NULL string */
p->ptr += 4;
if (out) {
*out = NULL;
}
if (out_len) {
*out_len = 0;
}
return TRUE;
} else if (len >= 0) {
const guint32 padded_len = G_ALIGN4(len + 1);
const char* str = (char*)(p->ptr + 4);
if ((p->ptr + padded_len + 4) <= p->end && !str[len]) {
p->ptr += padded_len + 4;
if (out) {
*out = str;
}
if (out_len) {
*out_len = len;
}
return TRUE;
}
}
}
return FALSE;
}
/* The equivalent of Android's Parcel::readString16 */
gboolean
gbinder_reader_read_nullable_string16(
GBinderReader* reader,
@@ -682,17 +726,20 @@ gbinder_reader_read_nullable_string16_utf16(
return TRUE;
} else if (len >= 0) {
const guint32 padded_len = G_ALIGN4((len + 1)*2);
const gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
if ((p->ptr + padded_len + 4) <= p->end) {
p->ptr += padded_len + 4;
if (out) {
*out = utf16;
const gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
if (!utf16[len]) {
p->ptr += padded_len + 4;
if (out) {
*out = utf16;
}
if (out_len) {
*out_len = len;
}
return TRUE;
}
if (out_len) {
*out_len = len;
}
return TRUE;
}
}
}
@@ -728,26 +775,7 @@ gboolean
gbinder_reader_skip_string16(
GBinderReader* reader)
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if ((p->ptr + 4) <= p->end) {
const gint32* len_ptr = (gint32*)p->ptr;
const gint32 len = *len_ptr;
if (len == -1) {
/* NULL string */
p->ptr += 4;
return TRUE;
} else if (len >= 0) {
const guint32 padded_len = G_ALIGN4((len+1)*2);
if ((p->ptr + padded_len + 4) <= p->end) {
p->ptr += padded_len + 4;
return TRUE;
}
}
}
return FALSE;
return gbinder_reader_read_nullable_string16_utf16(reader, NULL, NULL);
}
const void*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -73,15 +73,12 @@ gbinder_remote_reply_set_data(
GBinderRemoteReply* self,
GBinderBuffer* buffer)
{
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
/* The caller checks the pointer for NULL */
GBinderReaderData* data = &self->data;
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
} else {
gbinder_buffer_free(buffer);
}
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
}
GBinderRemoteReply*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -162,29 +162,25 @@ gbinder_remote_request_set_data(
guint32 txcode,
GBinderBuffer* buffer)
{
/* The caller never passes NULL req */
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
GBinderReaderData* data = &self->data;
GBinderReader reader;
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
GBinderReader reader;
g_free(self->iface2);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
g_free(self->iface2);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
/* Parse RPC header */
gbinder_remote_request_init_reader2(self, &reader);
self->iface = self->protocol->read_rpc_header(&reader, txcode,
&self->iface2);
if (self->iface) {
self->header_size = gbinder_reader_bytes_read(&reader);
} else {
/* No RPC header */
self->header_size = 0;
}
/* Parse RPC header */
gbinder_remote_request_init_reader2(self, &reader);
self->iface = self->protocol->read_rpc_header(&reader, txcode,
&self->iface2);
if (self->iface) {
self->header_size = gbinder_reader_bytes_read(&reader);
} else {
gbinder_buffer_free(buffer);
/* No RPC header */
self->header_size = 0;
}
}

View File

@@ -35,6 +35,9 @@
#include "gbinder_writer.h"
#include "gbinder_config.h"
#include "gbinder_log.h"
#include "gbinder_local_object_p.h"
#include <string.h>
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
@@ -218,7 +221,11 @@ gbinder_rpc_protocol_aidl3_finish_flatten_binder(
void* out,
GBinderLocalObject* obj)
{
*(guint32*)out = GBINDER_STABILITY_SYSTEM;
if (G_LIKELY(obj)) {
*(guint32*)out = obj->stability;
} else {
*(guint32*)out = GBINDER_STABILITY_UNDECLARED;
}
}
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl3 = {
@@ -231,6 +238,44 @@ static const GBinderRpcProtocol gbinder_rpc_protocol_aidl3 = {
.finish_flatten_binder = gbinder_rpc_protocol_aidl3_finish_flatten_binder
};
/*==========================================================================*
* AIDL protocol appeared in Android 12 (API level 31), but reverted in
* Android 13 (API level 33).
*==========================================================================*/
#define BINDER_WIRE_FORMAT_VERSION_AIDL4 1
struct stability_category {
guint8 binder_wire_format_version;
guint8 reserved[2];
guint8 stability_level;
};
G_STATIC_ASSERT(sizeof(struct stability_category) == sizeof(guint32));
static
void
gbinder_rpc_protocol_aidl4_finish_flatten_binder(
void* out,
GBinderLocalObject* obj)
{
struct stability_category cat = {
.binder_wire_format_version = BINDER_WIRE_FORMAT_VERSION_AIDL4,
.reserved = { 0, 0, },
.stability_level = obj ? obj->stability : GBINDER_STABILITY_UNDECLARED,
};
memcpy(out, &cat, sizeof(cat));
}
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl4 = {
.name = "aidl4",
.ping_tx = GBINDER_PING_TRANSACTION,
.write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
.write_rpc_header = gbinder_rpc_protocol_aidl3_write_rpc_header,
.read_rpc_header = gbinder_rpc_protocol_aidl3_read_rpc_header,
.flat_binder_object_extra = 4,
.finish_flatten_binder = gbinder_rpc_protocol_aidl4_finish_flatten_binder
};
/*==========================================================================*
* The original /dev/hwbinder protocol.
*==========================================================================*/
@@ -284,6 +329,7 @@ static const GBinderRpcProtocol* gbinder_rpc_protocol_list[] = {
&gbinder_rpc_protocol_aidl,
&gbinder_rpc_protocol_aidl2,
&gbinder_rpc_protocol_aidl3,
&gbinder_rpc_protocol_aidl4,
&gbinder_rpc_protocol_hidl
};

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -993,36 +993,33 @@ gbinder_servicemanager_remove_handlers(
guint count) /* Since 1.0.25 */
{
if (G_LIKELY(self) && G_LIKELY(ids) && G_LIKELY(count)) {
guint i, disconnected = 0;
GBinderServiceManagerClass* klass =
GBINDER_SERVICEMANAGER_GET_CLASS(self);
GBinderServiceManagerPriv* priv = self->priv;
GHashTableIter it;
gpointer value;
for (i = 0; i < count; i++) {
if (ids[i]) {
g_signal_handler_disconnect(self, ids[i]);
disconnected++;
ids[i] = 0;
}
}
gutil_disconnect_handlers(self, ids, count);
if (disconnected) {
GBinderServiceManagerClass* klass =
GBINDER_SERVICEMANAGER_GET_CLASS(self);
GBinderServiceManagerPriv* priv = self->priv;
GHashTableIter it;
gpointer value;
/*
* Regardless of whether we have actually removed any handlers, still
* check all watchers because there's a possibility that some handlers
* got removed with a straight g_signal_handler_disconnect() call.
*/
g_hash_table_iter_init(&it, priv->watch_table);
while (g_hash_table_iter_next(&it, NULL, &value)) {
GBinderServiceManagerWatch* watch = value;
g_hash_table_iter_init(&it, priv->watch_table);
while (disconnected && g_hash_table_iter_next(&it, NULL, &value)) {
GBinderServiceManagerWatch* watch = value;
if (watch->watched && !g_signal_has_handler_pending(self,
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
watch->quark, TRUE)) {
/* This must be one of those we have just removed */
GDEBUG("Unwatching %s", watch->name);
if (!g_signal_has_handler_pending(self,
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
watch->quark, TRUE)) {
/* No need to keep the watch around if no one is listening */
GDEBUG("Dropping watch %s", watch->name);
if (watch->watched) {
watch->watched = FALSE;
klass->unwatch(self, watch->name);
disconnected--;
}
g_hash_table_iter_remove(&it);
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -45,8 +45,15 @@
typedef struct gbinder_servicemanager_hidl_watch {
char* name;
GBinderLocalObject* callback;
GBinderClient* client;
gulong tx_id;
} GBinderServiceManagerHidlWatch;
typedef struct gbinder_servicemanager_hidl_watch_call {
GBinderLocalObject* callback;
GBinderServiceManagerHidlWatch* watch;
} GBinderServiceManagerHidlWatchCall;
typedef GBinderServiceManagerClass GBinderServiceManagerHidlClass;
typedef struct gbinder_servicemanager_hidl {
GBinderServiceManager manager;
@@ -253,11 +260,68 @@ gbinder_servicemanager_hidl_watch_free(
{
GBinderServiceManagerHidlWatch* watch = data;
g_free(watch->name);
gbinder_local_object_drop(watch->callback);
gbinder_client_cancel(watch->client, watch->tx_id);
gbinder_client_unref(watch->client);
g_free(watch->name);
g_free(watch);
}
static
void
gbinder_servicemanager_hidl_watch_call_reply(
GBinderClient* client,
GBinderRemoteReply* reply,
int tx_status,
void* user_data)
{
GBinderServiceManagerHidlWatchCall* call = user_data;
GBinderServiceManagerHidlWatch* watch = call->watch;
/*
* We can only get here if the call wasn't cancelled by
* gbinder_servicemanager_hidl_watch_free() meaning that
* we can safely access GBinderServiceManagerHidlWatch.
*/
watch->tx_id = 0;
if (tx_status == GBINDER_STATUS_OK) {
GBinderReader reader;
gint32 status;
gboolean success;
gbinder_remote_reply_init_reader(reply, &reader);
if (gbinder_reader_read_int32(&reader, &status) &&
gbinder_reader_read_bool(&reader, &success)) {
if (status == GBINDER_STATUS_OK && success) {
/* Successfully registered */
return;
} else {
GWARN("registerForNotifications(%s) failed", watch->name);
}
} else {
GWARN("Unexpected registerForNotifications(%s) reply", watch->name);
}
} else {
GWARN("registerForNotifications(%s) tx failed", watch->name);
}
/* There's no need to keep this object around if its registration failed */
gbinder_local_object_drop(watch->callback);
watch->callback = NULL;
}
static
void
gbinder_servicemanager_hidl_watch_call_destroy(
void* user_data)
{
GBinderServiceManagerHidlWatchCall* call = user_data;
/* call->watch may be destroyed by now, don't touch it */
gbinder_local_object_unref(call->callback);
g_free(call);
}
static
GBINDER_SERVICEMANAGER_NAME_CHECK
gbinder_servicemanager_hidl_check_name(
@@ -297,13 +361,13 @@ gbinder_servicemanager_hidl_watch(
{
GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(manager);
GBinderLocalRequest* req = gbinder_client_new_request(manager->client);
GBinderRemoteReply* reply;
GBinderServiceManagerHidlWatch* watch =
g_new0(GBinderServiceManagerHidlWatch, 1);
gboolean success = FALSE;
int status;
GBinderServiceManagerHidlWatchCall* call =
g_new0(GBinderServiceManagerHidlWatchCall, 1);
watch->name = g_strdup(name);
watch->client = gbinder_client_ref(manager->client);
watch->callback = gbinder_servicemanager_new_local_object(manager,
SERVICEMANAGER_HIDL_NOTIFICATION_IFACE,
gbinder_servicemanager_hidl_notification, self);
@@ -314,26 +378,37 @@ gbinder_servicemanager_hidl_watch(
gbinder_local_request_append_hidl_string(req, name);
gbinder_local_request_append_hidl_string(req, "");
gbinder_local_request_append_local_object(req, watch->callback);
reply = gbinder_client_transact_sync_reply(manager->client,
REGISTER_FOR_NOTIFICATIONS_TRANSACTION, req, &status);
if (status == GBINDER_STATUS_OK && reply) {
GBinderReader reader;
gbinder_remote_reply_init_reader(reply, &reader);
if (gbinder_reader_read_int32(&reader, &status) &&
status == GBINDER_STATUS_OK) {
gbinder_reader_read_bool(&reader, &success);
}
}
gbinder_remote_reply_unref(reply);
/*
* GBinderServiceManagerHidlWatchCall keeps the additional reference
* to the callback object for the duration of the transaction. Since
* the transaction is asynchronous, the object may be unrefed before
* the transaction actually gets submitted, and we don't want to pass
* an invalid object pointer to the kernel. This extra ref makes sure
* that the pointer remains valid.
*/
call->watch = watch;
call->callback = gbinder_local_object_ref(watch->callback);
watch->tx_id = gbinder_client_transact(watch->client,
REGISTER_FOR_NOTIFICATIONS_TRANSACTION, 0, req,
gbinder_servicemanager_hidl_watch_call_reply,
gbinder_servicemanager_hidl_watch_call_destroy, call);
gbinder_local_request_unref(req);
if (!success) {
if (watch->tx_id) {
/*
* At this point, we don't really know whether the registration
* will actually succeed. Since in the worst case we just won't
* get any notifications, I don't see a good enough reason to
* complicate the internal interface to handle such an unlikely
* and non-critical issue.
*/
return TRUE;
} else {
/* unwatch() won't be called if we return FALSE */
g_hash_table_remove(self->watch_table, watch->name);
return FALSE;
}
return success;
}
static

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -40,13 +40,12 @@
#include <glib-object.h>
typedef struct gbinder_servicemanager_priv GBinderServiceManagerPriv;
typedef struct gbinder_servicemanager {
struct gbinder_servicemanager {
GObject parent;
GBinderServiceManagerPriv* priv;
const char* dev;
GBinderClient* client;
} GBinderServiceManager;
};
typedef enum gbinder_servicemanager_name_check {
GBINDER_SERVICEMANAGER_NAME_OK,

View File

@@ -77,13 +77,6 @@ typedef struct gbinder_ipc_sync_api GBinderIpcSyncApi;
/* As a special case, ServiceManager's handle is zero */
#define GBINDER_SERVICEMANAGER_HANDLE (0)
typedef enum gbinder_stability_level {
GBINDER_STABILITY_UNDECLARED = 0,
GBINDER_STABILITY_VENDOR = 0x03,
GBINDER_STABILITY_SYSTEM = 0x0c,
GBINDER_STABILITY_VINTF = 0x3f
} GBINDER_STABILITY_LEVEL;
#endif /* GBINDER_TYPES_PRIVATE_H */
/*

View File

@@ -1176,8 +1176,11 @@ gbinder_writer_data_append_local_object(
n = data->io->encode_local_object(buf->data + offset, obj, data->protocol);
/* Fix the data size */
g_byte_array_set_size(buf, offset + n);
/* Record the offset */
gbinder_writer_data_record_offset(data, offset);
if (obj) {
/* Record the offset */
gbinder_writer_data_record_offset(data, offset);
}
}
void
@@ -1308,8 +1311,11 @@ gbinder_writer_data_append_remote_object(
n = data->io->encode_remote_object(buf->data + offset, obj);
/* Fix the data size */
g_byte_array_set_size(buf, offset + n);
/* Record the offset */
gbinder_writer_data_record_offset(data, offset);
if (obj) {
/* Record the offset */
gbinder_writer_data_record_offset(data, offset);
}
}
static

View File

@@ -531,11 +531,25 @@ static const TestPresetsData test_presets_data [] = {
"[General]\n"
"ApiLevel = 31\n"
"[Protocol]\n"
"/dev/binder = aidl4\n"
"/dev/vndbinder = aidl4\n"
"[ServiceManager]\n"
"/dev/binder = aidl3\n"
"/dev/vndbinder = aidl3\n"
},{
"33",
"[General]\n"
"ApiLevel = 33",
"[General]\n"
"ApiLevel = 33\n"
"[Protocol]\n"
"/dev/binder = aidl3\n"
"/dev/vndbinder = aidl3\n"
"[ServiceManager]\n"
"/dev/binder = aidl4\n"
"/dev/vndbinder = aidl4\n"
"/dev/binder = aidl3\n"
"/dev/vndbinder = aidl3\n"
}
};

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -51,6 +51,7 @@
#include <sys/types.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-ipc-XXXXXX";
static
gboolean
@@ -1346,6 +1347,9 @@ test_cancel_on_exit(
int main(int argc, char* argv[])
{
TestConfig test_config;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -1375,7 +1379,10 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("drop_remote_refs"), test_drop_remote_refs);
g_test_add_func(TEST_("cancel_on_exit"), test_cancel_on_exit);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
result = g_test_run();
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
*
* You may use this file under the terms of BSD license as follows:
@@ -140,6 +140,8 @@ test_null(
gbinder_local_object_handle_decrefs(NULL);
gbinder_local_object_handle_acquire(NULL, NULL);
gbinder_local_object_handle_release(NULL);
gbinder_local_object_handle_release(NULL);
gbinder_local_object_set_stability(NULL, GBINDER_STABILITY_UNDECLARED);
}
/*==========================================================================*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -46,6 +46,7 @@
#include <gutil_intarray.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-local-reply-XXXXXX";
static
void
@@ -453,10 +454,7 @@ test_local_object(
reply = test_local_reply_new();
gbinder_local_reply_append_local_object(reply, NULL);
data = gbinder_local_reply_data(reply);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert_cmpuint(offsets->count, == ,1);
g_assert_cmpuint(offsets->data[0], == ,0);
g_assert(!gbinder_output_data_offsets(data));
g_assert_cmpuint(gbinder_output_data_buffers_size(data), == ,0);
g_assert_cmpuint(data->bytes->len, == ,BINDER_OBJECT_SIZE_32);
gbinder_local_reply_unref(reply);
@@ -474,14 +472,10 @@ test_remote_object(
{
GBinderLocalReply* reply = test_local_reply_new();
GBinderOutputData* data;
GUtilIntArray* offsets;
gbinder_local_reply_append_remote_object(reply, NULL);
data = gbinder_local_reply_data(reply);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert(offsets->count == 1);
g_assert(offsets->data[0] == 0);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
gbinder_local_reply_unref(reply);
@@ -538,6 +532,9 @@ test_remote_reply(
int main(int argc, char* argv[])
{
TestConfig test_config;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -558,7 +555,10 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
g_test_add_func(TEST_PREFIX "remote_reply", test_remote_reply);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
result = g_test_run();
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -33,6 +33,7 @@
#include "test_common.h"
#include "test_binder.h"
#include "gbinder_local_object.h"
#include "gbinder_local_request_p.h"
#include "gbinder_output_data.h"
#include "gbinder_rpc_protocol.h"
@@ -40,10 +41,12 @@
#include "gbinder_driver.h"
#include "gbinder_writer.h"
#include "gbinder_io.h"
#include "gbinder_ipc.h"
#include <gutil_intarray.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-local-request-XXXXXX";
static
void
@@ -431,19 +434,36 @@ void
test_local_object(
void)
{
GBinderLocalRequest* req = test_local_request_new();
GBinderLocalRequest* req;
GBinderOutputData* data;
GUtilIntArray* offsets;
GBinderIpc* ipc = gbinder_ipc_new(NULL, NULL);
const char* const ifaces[] = { "android.hidl.base@1.0::IBase", NULL };
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
gbinder_local_request_append_local_object(req, NULL);
/* Append a real object */
req = test_local_request_new();
gbinder_local_request_append_local_object(req, obj);
data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert(offsets->count == 1);
g_assert(offsets->data[0] == 0);
g_assert_cmpuint(offsets->count, == ,1);
g_assert_cmpuint(offsets->data[0], == ,0);
g_assert_cmpuint(gbinder_output_data_buffers_size(data), == ,0);
g_assert_cmpuint(data->bytes->len, == ,BINDER_OBJECT_SIZE_32);
gbinder_local_request_unref(req);
/* Append NULL object */
req = test_local_request_new();
gbinder_local_request_append_local_object(req, NULL);
data = gbinder_local_request_data(req);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
gbinder_local_request_unref(req);
gbinder_local_object_unref(obj);
gbinder_ipc_unref(ipc);
}
/*==========================================================================*
@@ -457,14 +477,10 @@ test_remote_object(
{
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
GUtilIntArray* offsets;
gbinder_local_request_append_remote_object(req, NULL);
data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert(offsets->count == 1);
g_assert(offsets->data[0] == 0);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
gbinder_local_request_unref(req);
@@ -538,12 +554,10 @@ test_remote_request_obj_validate_data(
const GByteArray* bytes = data->bytes;
GUtilIntArray* offsets = gbinder_output_data_offsets(data);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert(offsets->count == 3);
g_assert(offsets->count == 2);
g_assert(offsets->data[0] == 4);
g_assert(offsets->data[1] == 4 + BUFFER_OBJECT_SIZE_64);
g_assert(offsets->data[2] == 4 + 2*BUFFER_OBJECT_SIZE_64);
g_assert(bytes->len == 4 + 2*BUFFER_OBJECT_SIZE_64 + BINDER_OBJECT_SIZE_64);
/* GBinderHidlString + the contents (2 bytes) aligned at 8-byte boundary */
g_assert(gbinder_output_data_buffers_size(data) ==
@@ -600,6 +614,9 @@ test_remote_request_obj(
int main(int argc, char* argv[])
{
TestConfig test_config;
int result;
g_test_init(&argc, &argv, NULL);
g_test_add_func(TEST_PREFIX "null", test_null);
g_test_add_func(TEST_PREFIX "cleanup", test_cleanup);
@@ -618,7 +635,10 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_PREFIX "remote_request", test_remote_request);
g_test_add_func(TEST_PREFIX "remote_request_obj", test_remote_request_obj);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
result = g_test_run();
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -1,7 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -194,6 +193,7 @@ void
test_bool(
void)
{
const guint8 in_short[] = { 0 };
const guint8 in_true[] = { TEST_INT8_BYTES_4(TRUE) };
const guint8 in_false[] = { TEST_INT8_BYTES_4(FALSE) };
gboolean out = FALSE;
@@ -203,10 +203,21 @@ test_bool(
g_assert(driver);
memset(&data, 0, sizeof(data));
/* not enough data */
data.buffer = gbinder_buffer_new(driver,
g_memdup(&in_true, sizeof(in_true)), sizeof(in_true), NULL);
g_memdup(TEST_ARRAY_AND_SIZE(in_short)), sizeof(in_short), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(!gbinder_reader_read_bool(&reader, NULL));
g_assert(!gbinder_reader_read_bool(&reader, &out));
g_assert(!gbinder_reader_at_end(&reader));
/* true */
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(in_true)), sizeof(in_true), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
@@ -219,7 +230,7 @@ test_bool(
/* false */
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(driver,
g_memdup(&in_false, sizeof(in_false)), sizeof(in_false), NULL);
g_memdup(TEST_ARRAY_AND_SIZE(in_false)), sizeof(in_false), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, NULL));
@@ -493,7 +504,7 @@ test_double(
}
/*==========================================================================*
* string8
* cstring
*==========================================================================*/
typedef struct test_string_data {
@@ -504,28 +515,28 @@ typedef struct test_string_data {
gboolean remaining;
} TestStringData;
static const guint8 test_string8_in_short [] = {
static const guint8 test_cstring_in_short [] = {
't', 'e', 's', 't', 0, 0, 0
};
static const guint8 test_string8_in_basic1 [] = {
static const guint8 test_cstring_in_basic1 [] = {
't', 'e', 's', 't', 0, 0, 0, 0
};
static const guint8 test_string8_in_basic2 [] = {
static const guint8 test_cstring_in_basic2 [] = {
't', 'e', 's', 't', 0, 0, 0, 0, 0
};
static const TestStringData test_string8_tests [] = {
{ "short", TEST_ARRAY_AND_SIZE(test_string8_in_short), NULL,
sizeof(test_string8_in_short)},
{ "ok1", TEST_ARRAY_AND_SIZE(test_string8_in_basic1), "test", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string8_in_basic2), "test", 1 }
static const TestStringData test_cstring_tests [] = {
{ "err", TEST_ARRAY_AND_SIZE(test_cstring_in_short), NULL,
sizeof(test_cstring_in_short)},
{ "ok1", TEST_ARRAY_AND_SIZE(test_cstring_in_basic1), "test", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_cstring_in_basic2), "test", 1 }
};
static
void
test_string8(
test_cstring(
gconstpointer test_data)
{
const TestStringData* test = test_data;
@@ -549,6 +560,119 @@ test_string8(
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string8
*==========================================================================*/
static const guint8 test_string8_in_null [] = {
TEST_INT32_BYTES(-1)
};
static const guint8 test_string8_in_invalid [] = {
TEST_INT32_BYTES(-2)
};
static const guint8 test_string8_in_short1 [] = {
0x00
};
static const guint8 test_string8_in_short2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o'
};
static const guint8 test_string8_in_noterm [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 'x' /* Missing terminator */
};
static const guint8 test_string8_in_basic1 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00
};
static const guint8 test_string8_in_basic2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00, 0x00
};
static const TestStringData test_string8_tests [] = {
{ "invalid", TEST_ARRAY_AND_SIZE(test_string8_in_invalid), NULL,
sizeof(test_string8_in_invalid) },
{ "short1", TEST_ARRAY_AND_SIZE(test_string8_in_short1), NULL,
sizeof(test_string8_in_short1) },
{ "short2", TEST_ARRAY_AND_SIZE(test_string8_in_short2), NULL,
sizeof(test_string8_in_short2) },
{ "noterm", TEST_ARRAY_AND_SIZE(test_string8_in_noterm), NULL,
sizeof(test_string8_in_noterm) },
{ "ok1", TEST_ARRAY_AND_SIZE(test_string8_in_basic1), "foo", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string8_in_basic2), "foo", 1 }
};
static
void
test_string8_null(
void)
{
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
gsize len = 1;
char dummy;
const char* out = &dummy;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(test_string8_in_null)),
sizeof(test_string8_in_null), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_skip_nullable_string8(&reader));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_read_nullable_string8(&reader, &out, &len));
g_assert(gbinder_reader_at_end(&reader));
g_assert(!out);
g_assert(!len);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
static
void
test_string8(
gconstpointer test_data)
{
const TestStringData* test = test_data;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader r;
GBinderReaderData data;
const gboolean valid = (test->out != NULL);
const char* out = NULL;
gsize len = 0;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
test->in_size, NULL);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_skip_nullable_string8(&r) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string8(&r, &out, &len) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
if (valid) {
g_assert_cmpstr(out, ==, test->out);
g_assert_cmpuint(len, == ,strlen(test->out));
}
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string16
*==========================================================================*/
@@ -567,6 +691,12 @@ static const guint8 test_string16_in_short [] = {
TEST_INT16_BYTES('o'), 0x00
};
static const guint8 test_string16_in_noterm [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
TEST_INT16_BYTES('o'), TEST_INT16_BYTES('o') /* Missing terminator */
};
static const guint8 test_string16_in_basic1 [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
@@ -584,6 +714,8 @@ static const TestStringData test_string16_tests [] = {
sizeof(test_string16_in_invalid) },
{ "short", TEST_ARRAY_AND_SIZE(test_string16_in_short), NULL,
sizeof(test_string16_in_short) },
{ "noterm", TEST_ARRAY_AND_SIZE(test_string16_in_noterm), NULL,
sizeof(test_string16_in_noterm) },
{ "ok1", TEST_ARRAY_AND_SIZE(test_string16_in_basic1), "foo", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string16_in_basic2), "foo", 1 }
};
@@ -2434,6 +2566,15 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("float"), test_float);
g_test_add_func(TEST_("double"), test_double);
for (i = 0; i < G_N_ELEMENTS(test_cstring_tests); i++) {
const TestStringData* test = test_cstring_tests + i;
char* path = g_strconcat(TEST_("cstring/"), test->name, NULL);
g_test_add_data_func(path, test, test_cstring);
g_free(path);
}
g_test_add_func(TEST_("string8/null"), test_string8_null);
for (i = 0; i < G_N_ELEMENTS(test_string8_tests); i++) {
const TestStringData* test = test_string8_tests + i;
char* path = g_strconcat(TEST_("string8/"), test->name, NULL);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -95,7 +95,6 @@ test_null(
g_assert(!gbinder_remote_reply_ref(NULL));
gbinder_remote_reply_unref(NULL);
gbinder_remote_reply_set_data(NULL, NULL);
gbinder_remote_reply_init_reader(NULL, &reader);
g_assert(gbinder_reader_at_end(&reader));
g_assert(gbinder_remote_reply_is_empty(NULL));

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
*
* You may use this file under the terms of BSD license as follows:
@@ -74,7 +74,6 @@ test_null(
g_assert(!gbinder_remote_request_ref(NULL));
gbinder_remote_request_unref(NULL);
gbinder_remote_request_set_data(NULL, 0, NULL);
gbinder_remote_request_init_reader(NULL, &reader);
gbinder_remote_request_block(NULL);
gbinder_remote_request_complete(NULL, NULL, 0);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
*
* You may use this file under the terms of BSD license as follows:
@@ -449,10 +449,13 @@ test_invalid(
{
int status = 0;
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestConfig config;
gulong id = 0;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
g_assert(!gbinder_servicemanager_new2(GBINDER_DEFAULT_HWBINDER, "a", NULL));
sm = gbinder_servicemanager_new(dev);
@@ -484,6 +487,7 @@ test_invalid(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -496,12 +500,13 @@ test_basic(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderIpc* ipc;
GBinderServiceManager* sm;
GBinderLocalObject* obj;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -530,11 +535,12 @@ test_legacy(
{
const char* otherdev = "/dev/otherbinder";
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_hwservicemanager_new(dev);
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
@@ -649,12 +655,14 @@ test_not_present(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestConfig config;
int fd;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, THIS_THREAD, -1);
@@ -679,16 +687,17 @@ test_wait(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
const glong forever = (test_opt.flags & TEST_FLAG_DEBUG) ?
(TEST_TIMEOUT_SEC * 1000) : -1;
GBinderIpc* ipc;
GBinderServiceManager* sm;
gulong id;
int count = 0;
int fd, count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, THIS_THREAD, -1);
@@ -734,14 +743,15 @@ test_wait_long(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GBinderIpc* ipc;
GBinderServiceManager* sm;
gulong id;
int count = 0;
int fd, count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, THIS_THREAD, -1);
@@ -784,15 +794,16 @@ test_wait_async(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
gulong id[2];
int count = 0;
int fd, count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, THIS_THREAD, -1);
@@ -832,15 +843,17 @@ void
test_death_run()
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
gulong id[3];
int count = 0, reg_count = 0;
int fd, count = 0, reg_count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -909,16 +922,18 @@ test_reanimate(
void)
{
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
gulong id[3];
int count = 0, reg_count = 0;
int fd, count = 0, reg_count = 0;
TestConfig config;
/* Create live service manager */
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
fd = gbinder_driver_fd(ipc->driver);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -965,9 +980,9 @@ test_reuse(
const char* binder_dev = GBINDER_DEFAULT_BINDER;
const char* vndbinder_dev = "/dev/vpnbinder";
const char* hwbinder_dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* binder_ipc = gbinder_ipc_new(binder_dev, NULL);
GBinderIpc* vndbinder_ipc = gbinder_ipc_new(vndbinder_dev, NULL);
GBinderIpc* hwbinder_ipc = gbinder_ipc_new(hwbinder_dev, NULL);
GBinderIpc* binder_ipc;
GBinderIpc* vndbinder_ipc;
GBinderIpc* hwbinder_ipc;
GBinderServiceManager* m1;
GBinderServiceManager* m2;
GBinderServiceManager* vnd1;
@@ -977,6 +992,10 @@ test_reuse(
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
binder_ipc = gbinder_ipc_new(binder_dev, NULL);
vndbinder_ipc = gbinder_ipc_new(vndbinder_dev, NULL);
hwbinder_ipc = gbinder_ipc_new(hwbinder_dev, NULL);
test_setup_ping(binder_ipc);
test_setup_ping(vndbinder_ipc);
test_setup_ping(hwbinder_ipc);
@@ -1023,7 +1042,7 @@ test_notify_type(
GType t,
const char* dev)
{
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestHwServiceManager* test;
const char* name = "foo";
@@ -1032,6 +1051,7 @@ test_notify_type(
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new_with_type(t, NULL, NULL);
test = TEST_SERVICEMANAGER2(sm, t);
@@ -1094,8 +1114,8 @@ test_list(
void)
{
const char* dev = GBINDER_DEFAULT_BINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestHwServiceManager* test;
char** list;
@@ -1103,6 +1123,7 @@ test_list(
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);
@@ -1146,8 +1167,8 @@ test_get(
void)
{
const char* dev = GBINDER_DEFAULT_BINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestHwServiceManager* test;
int status = -1;
@@ -1156,6 +1177,7 @@ test_get(
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);
@@ -1211,8 +1233,8 @@ test_add(
void)
{
const char* dev = GBINDER_DEFAULT_BINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderIpc* ipc;
GBinderServiceManager* sm;
TestHwServiceManager* test;
GBinderLocalObject* obj;
@@ -1220,6 +1242,7 @@ test_add(
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
ipc = gbinder_ipc_new(dev, NULL);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2021-2024 Slava Monich <slava@monich.com>
* Copyright (C) 2021-2022 Jolla Ltd.
*
* You may use this file under the terms of BSD license as follows:
@@ -333,6 +333,16 @@ test_notify_add_cb(
}
}
static
void
test_notify_unreached_cb(
GBinderServiceManager* sm,
const char* name,
void* user_data)
{
g_assert_not_reached();
}
static
void
test_notify_cb(
@@ -384,7 +394,13 @@ test_notify_run()
g_assert(!gbinder_servicemanager_add_registration_handler(sm, ",",
test_notify_never, NULL));
/* Start watching */
/* Register and immediately unregister the handler */
id = gbinder_servicemanager_add_registration_handler(sm, name,
test_notify_unreached_cb, NULL);
g_assert(id);
gbinder_servicemanager_remove_handler(sm, id);
/* Actually start watching */
id = gbinder_servicemanager_add_registration_handler(sm, name,
test_notify_cb, &test);
g_assert(id);

View File

@@ -1350,7 +1350,6 @@ test_local_object(
const TestLocalObjectData* test = test_data;
GBinderLocalRequest* req;
GBinderOutputData* data;
GUtilIntArray* offsets;
GBinderWriter writer;
TestContext context;
@@ -1359,10 +1358,7 @@ test_local_object(
gbinder_local_request_init_writer(req, &writer);
gbinder_writer_append_local_object(&writer, NULL);
data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert_cmpuint(offsets->count, == ,1);
g_assert_cmpuint(offsets->data[0], == ,0);
g_assert(!gbinder_output_data_offsets(data));
g_assert_cmpuint(gbinder_output_data_buffers_size(data), == ,0);
g_assert_cmpuint(data->bytes->len, == ,test->objsize);
gbinder_local_request_unref(req);
@@ -1380,7 +1376,6 @@ test_remote_object(
{
GBinderLocalRequest* req = test_local_request_new_64();
GBinderOutputData* data;
GUtilIntArray* offsets;
GBinderWriter writer;
TestContext test;
@@ -1388,10 +1383,7 @@ test_remote_object(
gbinder_local_request_init_writer(req, &writer);
gbinder_writer_append_remote_object(&writer, NULL);
data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert(offsets->count == 1);
g_assert(offsets->data[0] == 0);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_64);
gbinder_local_request_unref(req);