Compare commits
	
		
			6 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					94ddc9f0e5 | ||
| 
						 | 
					370d2dedb3 | ||
| 
						 | 
					58c9a7fe93 | ||
| 
						 | 
					3742e2ca8e | ||
| 
						 | 
					ede15da9e2 | ||
| 
						 | 
					771444a8ac | 
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 1
 | 
			
		||||
VERSION_RELEASE = 21
 | 
			
		||||
VERSION_RELEASE = 22
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
@@ -105,6 +105,7 @@ SRC += \
 | 
			
		||||
  gbinder_servicemanager_aidl.c \
 | 
			
		||||
  gbinder_servicemanager_aidl2.c \
 | 
			
		||||
  gbinder_servicemanager_aidl3.c \
 | 
			
		||||
  gbinder_servicemanager_aidl4.c \
 | 
			
		||||
  gbinder_servicemanager_hidl.c
 | 
			
		||||
 | 
			
		||||
SRC += \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,10 @@
 | 
			
		||||
libgbinder (1.1.22) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added support for Android 12 (API level 31)
 | 
			
		||||
  * Made binder device configurable for binder-dump
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 22 Jun 2022 17:02:20 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.21) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Made Properly finalize GBinderIpc and GBinderServicePoll
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
Name: libgbinder
 | 
			
		||||
 | 
			
		||||
Version: 1.1.21
 | 
			
		||||
Version: 1.1.22
 | 
			
		||||
Release: 0
 | 
			
		||||
Summary: Binder client library
 | 
			
		||||
License: BSD
 | 
			
		||||
 
 | 
			
		||||
@@ -133,9 +133,24 @@ static const GBinderConfigPresetGroup gbinder_config_30[] = {
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* API level 31 */
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPresetEntry gbinder_config_31_servicemanager[] = {
 | 
			
		||||
    { "/dev/binder", "aidl4" },
 | 
			
		||||
    { "/dev/vndbinder", "aidl4" },
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPresetGroup gbinder_config_31[] = {
 | 
			
		||||
    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
 | 
			
		||||
    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_31_servicemanager },
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Presets sorted by API level in descending order */
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPreset gbinder_config_presets[] = {
 | 
			
		||||
    { 31, gbinder_config_31 },
 | 
			
		||||
    { 30, gbinder_config_30 },
 | 
			
		||||
    { 29, gbinder_config_29 },
 | 
			
		||||
    { 28, gbinder_config_28 }
 | 
			
		||||
 
 | 
			
		||||
@@ -83,11 +83,12 @@ static const GBinderServiceManagerType gbinder_servicemanager_types[] = {
 | 
			
		||||
    { "aidl", gbinder_servicemanager_aidl_get_type },
 | 
			
		||||
    { "aidl2", gbinder_servicemanager_aidl2_get_type },
 | 
			
		||||
    { "aidl3", gbinder_servicemanager_aidl3_get_type },
 | 
			
		||||
    { "aidl4", gbinder_servicemanager_aidl4_get_type },
 | 
			
		||||
    { "hidl", gbinder_servicemanager_hidl_get_type }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SERVICEMANAGER_TYPE_AIDL (gbinder_servicemanager_types + 0)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 3)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 4)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_DEFAULT SERVICEMANAGER_TYPE_AIDL
 | 
			
		||||
 | 
			
		||||
static GHashTable* gbinder_servicemanager_map = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,13 @@ enum gbinder_servicemanager_aidl_calls {
 | 
			
		||||
    LIST_SERVICES_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DUMP_FLAG_PRIORITY_DEFAULT (0x08)
 | 
			
		||||
#define DUMP_FLAG_PRIORITY_ALL     (0x0f)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl.h"
 | 
			
		||||
#include "gbinder_servicemanager_aidl_p.h"
 | 
			
		||||
#include "gbinder_client_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
 | 
			
		||||
@@ -50,14 +50,6 @@ G_DEFINE_TYPE(GBinderServiceManagerAidl3,
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_servicemanager_aidl3_parent_class
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
@@ -84,28 +76,6 @@ gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl3_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * Starting from Android 11, to add a service, Android framework requires
 | 
			
		||||
     * an additional field `stability` when reading a strong binder.
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, SYSTEM);
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
char**
 | 
			
		||||
gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
@@ -148,6 +118,27 @@ gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    return (char**)g_ptr_array_free(list, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl3_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * Starting from Android 11, to add a service, Android framework requires
 | 
			
		||||
     * an additional field `stability` when reading a strong binder.
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, SYSTEM);
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl3_init(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
			
		||||
 * Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   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 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
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl_p.h"
 | 
			
		||||
#include "gbinder_client_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "binder.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_local_request.h>
 | 
			
		||||
#include <gbinder_remote_reply.h>
 | 
			
		||||
 | 
			
		||||
/* Variant of AIDL servicemanager appeared in Android 12 (API level 31) */
 | 
			
		||||
 | 
			
		||||
typedef GBinderServiceManagerAidl GBinderServiceManagerAidl4;
 | 
			
		||||
typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl4Class;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(GBinderServiceManagerAidl4,
 | 
			
		||||
    gbinder_servicemanager_aidl4,
 | 
			
		||||
    GBINDER_TYPE_SERVICEMANAGER_AIDL)
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_servicemanager_aidl4_parent_class
 | 
			
		||||
 | 
			
		||||
#define BINDER_WIRE_FORMAT_VERSION (1)
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl4_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * When reading nullable strong binder, from Android 12, the format of
 | 
			
		||||
     * the `stability` field passed on the wire was changed and evolved to
 | 
			
		||||
     * `struct Category`, which consists of the following members with 4 bytes long.
 | 
			
		||||
     *
 | 
			
		||||
     * struct Category {
 | 
			
		||||
     *   uint8_t version;
 | 
			
		||||
     *   uint8_t reserved[2];
 | 
			
		||||
     *   Level level;        <- bitmask of Stability::Level
 | 
			
		||||
     * }
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, B_PACK_CHARS(SYSTEM, 0, 0, BINDER_WIRE_FORMAT_VERSION));
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl4_init(
 | 
			
		||||
    GBinderServiceManagerAidl* self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl4_class_init(
 | 
			
		||||
    GBinderServiceManagerAidl4Class* cls)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(cls);
 | 
			
		||||
    cls->add_service_req = gbinder_servicemanager_aidl4_add_service_req;
 | 
			
		||||
    manager->list = gbinder_servicemanager_aidl3_list;
 | 
			
		||||
    manager->get_service = gbinder_servicemanager_aidl3_get_service;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   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 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
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
			
		||||
#define GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl.h"
 | 
			
		||||
 | 
			
		||||
char**
 | 
			
		||||
gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const GBinderIpcSyncApi* api)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    int* status,
 | 
			
		||||
    const GBinderIpcSyncApi* api)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -112,6 +112,7 @@ gbinder_servicemanager_exit(
 | 
			
		||||
GType gbinder_servicemanager_aidl_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl2_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl3_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl4_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_hidl_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -171,6 +171,8 @@ app_init(
 | 
			
		||||
          app_log_verbose, "Enable verbose output", NULL },
 | 
			
		||||
        { "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
 | 
			
		||||
          app_log_quiet, "Be quiet", NULL },
 | 
			
		||||
        { "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
 | 
			
		||||
          "Binder device [" DEV_DEFAULT "]", "DEVICE" },
 | 
			
		||||
        { NULL }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -187,7 +189,7 @@ app_init(
 | 
			
		||||
    if (g_option_context_parse(options, &argc, &argv, &error)) {
 | 
			
		||||
        char* help;
 | 
			
		||||
 | 
			
		||||
        opt->dev = g_strdup(DEV_DEFAULT);
 | 
			
		||||
        if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEV_DEFAULT);
 | 
			
		||||
        switch (argc) {
 | 
			
		||||
        case 2:
 | 
			
		||||
            opt->service = argv[1];
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ all:
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl2 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl3 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl4 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_hidl $*
 | 
			
		||||
	@$(MAKE) -C unit_servicename $*
 | 
			
		||||
	@$(MAKE) -C unit_servicepoll $*
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ unit_servicemanager \
 | 
			
		||||
unit_servicemanager_aidl \
 | 
			
		||||
unit_servicemanager_aidl2 \
 | 
			
		||||
unit_servicemanager_aidl3 \
 | 
			
		||||
unit_servicemanager_aidl4 \
 | 
			
		||||
unit_servicemanager_hidl \
 | 
			
		||||
unit_servicename \
 | 
			
		||||
unit_servicepoll \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -231,6 +231,7 @@ test_dirs(
 | 
			
		||||
    char* file1 = g_build_filename(subdir, "a.conf", NULL);
 | 
			
		||||
    char* file2 = g_build_filename(subdir, "b.conf", NULL);
 | 
			
		||||
    char* file3 = g_build_filename(subdir, "c.conf", NULL);
 | 
			
		||||
    char* file4 = g_build_filename(subdir, "d.conf", NULL);
 | 
			
		||||
    char* random_file = g_build_filename(subdir, "foo", NULL);
 | 
			
		||||
    static const char garbage[] = "foo";
 | 
			
		||||
    static const char config[] =
 | 
			
		||||
@@ -252,6 +253,11 @@ test_dirs(
 | 
			
		||||
        "/dev/binder3 = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder3 = aidl3\n";
 | 
			
		||||
    static const char config4[] =
 | 
			
		||||
        "[Protocol]\n"
 | 
			
		||||
        "/dev/binder4 = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder4 = aidl4\n";
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpint(mkdir(subdir, 0700), == ,0);
 | 
			
		||||
    g_assert_cmpint(mkdir(notafile, 0700), == ,0);
 | 
			
		||||
@@ -259,6 +265,7 @@ test_dirs(
 | 
			
		||||
    g_assert(g_file_set_contents(file1, config1, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file2, config2, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file3, config3, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file4, config4, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(random_file, garbage, -1, NULL));
 | 
			
		||||
 | 
			
		||||
    /* Reset the state */
 | 
			
		||||
@@ -271,10 +278,12 @@ test_dirs(
 | 
			
		||||
    g_assert(k);
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Remove the default file and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -284,9 +293,11 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Damage one of the files and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -297,8 +308,10 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Disallow access to one of the files and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -309,14 +322,27 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Delete the remaining files and try again */
 | 
			
		||||
    /* Leave only one file (file4) in the subdirectory */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
    g_assert_cmpint(remove(file1), == ,0);
 | 
			
		||||
    g_assert_cmpint(remove(file2), == ,0);
 | 
			
		||||
    g_assert_cmpint(remove(file3), == ,0);
 | 
			
		||||
    k = gbinder_config_get();
 | 
			
		||||
    g_assert(k);
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/binder3",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Delete the remaining file and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
    g_assert_cmpint(remove(file4), == ,0);
 | 
			
		||||
    g_assert(!gbinder_config_get());
 | 
			
		||||
 | 
			
		||||
    /* Undo all the damage */
 | 
			
		||||
@@ -329,6 +355,7 @@ test_dirs(
 | 
			
		||||
    g_free(file1);
 | 
			
		||||
    g_free(file2);
 | 
			
		||||
    g_free(file3);
 | 
			
		||||
    g_free(file4);
 | 
			
		||||
    g_free(random_file);
 | 
			
		||||
 | 
			
		||||
    remove(notafile);
 | 
			
		||||
@@ -495,6 +522,20 @@ static const TestPresetsData test_presets_data [] = {
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "/dev/vndbinder = aidl3\n"
 | 
			
		||||
    },{
 | 
			
		||||
        "31",
 | 
			
		||||
 | 
			
		||||
        "[General]\n"
 | 
			
		||||
        "ApiLevel = 31",
 | 
			
		||||
 | 
			
		||||
        "[General]\n"
 | 
			
		||||
        "ApiLevel = 31\n"
 | 
			
		||||
        "[Protocol]\n"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "/dev/vndbinder = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder = aidl4\n"
 | 
			
		||||
        "/dev/vndbinder = aidl4\n"
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -399,6 +399,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test service manager
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_servicemanager_aidl4/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_servicemanager_aidl4/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_servicemanager_aidl4
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										488
									
								
								unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,488 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   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 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
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_config.h"
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_reader.h"
 | 
			
		||||
#include "gbinder_servicemanager_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_local_object_p.h"
 | 
			
		||||
#include "gbinder_local_reply.h"
 | 
			
		||||
#include "gbinder_remote_request.h"
 | 
			
		||||
#include "gbinder_remote_object.h"
 | 
			
		||||
#include "gbinder_writer.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_strv.h>
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
static const char TMP_DIR_TEMPLATE[] =
 | 
			
		||||
    "gbinder-test-servicemanager_aidl4-XXXXXX";
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test service manager
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define SVCMGR_HANDLE (0)
 | 
			
		||||
static const char SVCMGR_IFACE[] = "android.os.IServiceManager";
 | 
			
		||||
enum servicemanager_aidl_tx {
 | 
			
		||||
    GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
			
		||||
    CHECK_SERVICE_TRANSACTION,
 | 
			
		||||
    ADD_SERVICE_TRANSACTION,
 | 
			
		||||
    LIST_SERVICES_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char* const servicemanager_aidl_ifaces[] = { SVCMGR_IFACE, NULL };
 | 
			
		||||
 | 
			
		||||
typedef GBinderLocalObjectClass ServiceManagerAidl4Class;
 | 
			
		||||
typedef struct service_manager_aidl4 {
 | 
			
		||||
    GBinderLocalObject parent;
 | 
			
		||||
    GHashTable* objects;
 | 
			
		||||
    gboolean handle_on_looper_thread;
 | 
			
		||||
} ServiceManagerAidl4;
 | 
			
		||||
 | 
			
		||||
#define SERVICE_MANAGER_AIDL4_TYPE (service_manager_aidl4_get_type())
 | 
			
		||||
#define SERVICE_MANAGER_AIDL4(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
        SERVICE_MANAGER_AIDL4_TYPE, ServiceManagerAidl4))
 | 
			
		||||
G_DEFINE_TYPE(ServiceManagerAidl4, service_manager_aidl4, \
 | 
			
		||||
        GBINDER_TYPE_LOCAL_OBJECT)
 | 
			
		||||
 | 
			
		||||
/* This is the format of stability passed on the wire. */
 | 
			
		||||
typedef struct category {
 | 
			
		||||
    /*
 | 
			
		||||
     * This is the version of the wire protocol associated with the host
 | 
			
		||||
     * process of a particular binder. As the wire protocol changes, if
 | 
			
		||||
     * sending a transaction to a binder with an old version, the Parcel
 | 
			
		||||
     * class must write parcels according to the version documented here.
 | 
			
		||||
     */
 | 
			
		||||
    gint8 version;
 | 
			
		||||
    gint8 reserved[2];
 | 
			
		||||
    gint8 level; /* bitmask of Stability::Level */
 | 
			
		||||
} Category;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
servicemanager_aidl4_handler(
 | 
			
		||||
    GBinderLocalObject* obj,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = user_data;
 | 
			
		||||
    GBinderLocalReply* reply = NULL;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderRemoteObject* remote_obj;
 | 
			
		||||
    guint32 allow_isolated, dumpsys_priority;
 | 
			
		||||
    char* str;
 | 
			
		||||
    Category category;
 | 
			
		||||
 | 
			
		||||
    g_assert(!flags);
 | 
			
		||||
    GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
 | 
			
		||||
    g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
 | 
			
		||||
    *status = -1;
 | 
			
		||||
    switch (code) {
 | 
			
		||||
    case GET_SERVICE_TRANSACTION:
 | 
			
		||||
    case CHECK_SERVICE_TRANSACTION:
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        str = gbinder_reader_read_string16(&reader);
 | 
			
		||||
        if (str) {
 | 
			
		||||
            reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
            remote_obj = g_hash_table_lookup(self->objects, str);
 | 
			
		||||
            if (remote_obj) {
 | 
			
		||||
                GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
                GDEBUG("Found name '%s' => %p", str, remote_obj);
 | 
			
		||||
                gbinder_local_reply_init_writer(reply, &writer);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, UNDECLARED);
 | 
			
		||||
                gbinder_writer_append_remote_object(&writer, remote_obj);
 | 
			
		||||
            } else {
 | 
			
		||||
                GDEBUG("Name '%s' not found", str);
 | 
			
		||||
                gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
 | 
			
		||||
            }
 | 
			
		||||
            g_free(str);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case ADD_SERVICE_TRANSACTION:
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        str = gbinder_reader_read_string16(&reader);
 | 
			
		||||
        remote_obj = gbinder_reader_read_object(&reader);
 | 
			
		||||
        gbinder_reader_read_uint32(&reader, (guint32*)&category);
 | 
			
		||||
        if (str && remote_obj &&
 | 
			
		||||
            category.level == SYSTEM &&
 | 
			
		||||
            category.version == 1 &&
 | 
			
		||||
            gbinder_reader_read_uint32(&reader, &allow_isolated) &&
 | 
			
		||||
            gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
 | 
			
		||||
            GDEBUG("Adding '%s'", str);
 | 
			
		||||
            g_hash_table_replace(self->objects, str, remote_obj);
 | 
			
		||||
            remote_obj = NULL;
 | 
			
		||||
            str = NULL;
 | 
			
		||||
            reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
            *status = GBINDER_STATUS_OK;
 | 
			
		||||
        }
 | 
			
		||||
        g_free(str);
 | 
			
		||||
        gbinder_remote_object_unref(remote_obj);
 | 
			
		||||
        break;
 | 
			
		||||
    case LIST_SERVICES_TRANSACTION:
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        if (gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
 | 
			
		||||
            if (g_hash_table_size(self->objects) == 1) {
 | 
			
		||||
                GList* keys = g_hash_table_get_keys(self->objects);
 | 
			
		||||
                GList* l = g_list_nth(keys, 0);
 | 
			
		||||
                gint32 srv_size = 1;
 | 
			
		||||
                GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
                reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
                gbinder_local_reply_init_writer(reply, &writer);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, srv_size);
 | 
			
		||||
                gbinder_writer_append_string16(&writer, l->data);
 | 
			
		||||
                g_list_free(keys);
 | 
			
		||||
                *status = GBINDER_STATUS_OK;
 | 
			
		||||
            } else {
 | 
			
		||||
                GDEBUG("Incorrect number of services %u",
 | 
			
		||||
                    g_hash_table_size(self->objects));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        GDEBUG("Unhandled command %u", code);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return reply;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
ServiceManagerAidl4*
 | 
			
		||||
servicemanager_aidl4_new(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    gboolean handle_on_looper_thread)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = g_object_new(SERVICE_MANAGER_AIDL4_TYPE, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 | 
			
		||||
    self->handle_on_looper_thread = handle_on_looper_thread;
 | 
			
		||||
    gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
 | 
			
		||||
        servicemanager_aidl4_handler, self);
 | 
			
		||||
    test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
 | 
			
		||||
    test_binder_register_object(fd, obj, SVCMGR_HANDLE);
 | 
			
		||||
    gbinder_ipc_register_local_object(ipc, obj);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
			
		||||
service_manager_aidl4_can_handle_transaction(
 | 
			
		||||
    GBinderLocalObject* object,
 | 
			
		||||
    const char* iface,
 | 
			
		||||
    guint code)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
 | 
			
		||||
 | 
			
		||||
    if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
 | 
			
		||||
        return GBINDER_LOCAL_TRANSACTION_LOOPER;
 | 
			
		||||
    } else {
 | 
			
		||||
        return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
 | 
			
		||||
            can_handle_transaction(object, iface, code);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
service_manager_aidl4_handle_looper_transaction(
 | 
			
		||||
    GBinderLocalObject* object,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
 | 
			
		||||
        return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
 | 
			
		||||
            handle_transaction(object, req, code, flags, status);
 | 
			
		||||
    } else {
 | 
			
		||||
        return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
 | 
			
		||||
            handle_looper_transaction(object, req, code, flags, status);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
 | 
			
		||||
 | 
			
		||||
    g_hash_table_destroy(self->objects);
 | 
			
		||||
    G_OBJECT_CLASS(service_manager_aidl4_parent_class)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_init(
 | 
			
		||||
    ServiceManagerAidl4* self)
 | 
			
		||||
{
 | 
			
		||||
    self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
 | 
			
		||||
        (GDestroyNotify) gbinder_remote_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_class_init(
 | 
			
		||||
    ServiceManagerAidl4Class* klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass* object = G_OBJECT_CLASS(klass);
 | 
			
		||||
    GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    object->finalize = service_manager_aidl4_finalize;
 | 
			
		||||
    local_object->can_handle_transaction =
 | 
			
		||||
        service_manager_aidl4_can_handle_transaction;
 | 
			
		||||
    local_object->handle_looper_transaction =
 | 
			
		||||
        service_manager_aidl4_handle_looper_transaction;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test context
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_context {
 | 
			
		||||
    const char* default_config_dir;
 | 
			
		||||
    const char* default_config_file;
 | 
			
		||||
    char* config_dir;
 | 
			
		||||
    char* config_subdir;
 | 
			
		||||
    char* config_file;
 | 
			
		||||
    GBinderLocalObject* object;
 | 
			
		||||
    ServiceManagerAidl4* service;
 | 
			
		||||
    GBinderServiceManager* client;
 | 
			
		||||
    int fd;
 | 
			
		||||
} TestContext;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_context_init(
 | 
			
		||||
    TestContext* test)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
 | 
			
		||||
    /*
 | 
			
		||||
     * Also set defaults so that both /dev/binder and /dev/binder-private
 | 
			
		||||
     * use the same protocol.
 | 
			
		||||
     */
 | 
			
		||||
    const char* config =
 | 
			
		||||
        "[Protocol]\n"
 | 
			
		||||
        "Default = aidl3\n"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "Default = aidl4\n"
 | 
			
		||||
        "/dev/binder = aidl4\n";
 | 
			
		||||
    GBinderIpc* ipc;
 | 
			
		||||
 | 
			
		||||
    memset(test, 0, sizeof(*test));
 | 
			
		||||
    test->default_config_dir = gbinder_config_dir;
 | 
			
		||||
    test->default_config_file = gbinder_config_file;
 | 
			
		||||
    test->config_dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
 | 
			
		||||
    test->config_subdir = g_build_filename(test->config_dir, "d", NULL);
 | 
			
		||||
    test->config_file = g_build_filename(test->config_dir, "test.conf", NULL);
 | 
			
		||||
    g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
 | 
			
		||||
    GDEBUG("Config file %s", test->config_file);
 | 
			
		||||
    gbinder_config_dir = test->config_subdir; /* Doesn't exist */
 | 
			
		||||
    gbinder_config_file = test->config_file;
 | 
			
		||||
 | 
			
		||||
    ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    test->fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    /* Set up binder simulator */
 | 
			
		||||
    test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
 | 
			
		||||
    test_binder_set_passthrough(test->fd, TRUE);
 | 
			
		||||
 | 
			
		||||
    test->service = servicemanager_aidl4_new(other_dev, TRUE);
 | 
			
		||||
    test->client = gbinder_servicemanager_new(dev);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_context_deinit(
 | 
			
		||||
    TestContext* test)
 | 
			
		||||
{
 | 
			
		||||
    test_binder_unregister_objects(test->fd);
 | 
			
		||||
    gbinder_local_object_unref(test->object);
 | 
			
		||||
    gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
 | 
			
		||||
    gbinder_servicemanager_unref(test->client);
 | 
			
		||||
    gbinder_ipc_exit();
 | 
			
		||||
    test_binder_exit_wait(&test_opt, NULL);
 | 
			
		||||
    remove(test->config_file);
 | 
			
		||||
    remove(test->config_dir);
 | 
			
		||||
    g_free(test->config_file);
 | 
			
		||||
    g_free(test->config_subdir);
 | 
			
		||||
    g_free(test->config_dir);
 | 
			
		||||
    gbinder_config_dir = test->default_config_dir;
 | 
			
		||||
    gbinder_config_file = test->default_config_file;
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * get
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_get_run()
 | 
			
		||||
{
 | 
			
		||||
    TestContext test;
 | 
			
		||||
    const char* name = "name";
 | 
			
		||||
    int status = -1;
 | 
			
		||||
 | 
			
		||||
    test_context_init(&test);
 | 
			
		||||
 | 
			
		||||
    /* Query the object (it's not there yet) */
 | 
			
		||||
    GDEBUG("Querying '%s'", name);
 | 
			
		||||
    g_assert(!gbinder_servicemanager_get_service_sync(test.client,
 | 
			
		||||
        name, &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    /* Register object */
 | 
			
		||||
    GDEBUG("Registering object '%s' => %p", name, test.object);
 | 
			
		||||
    g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
 | 
			
		||||
        name, test.object), == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
 | 
			
		||||
    g_assert(g_hash_table_contains(test.service->objects, name));
 | 
			
		||||
 | 
			
		||||
    /* Query the object (this time it must be there) */
 | 
			
		||||
    GDEBUG("Querying '%s' again", name);
 | 
			
		||||
    g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
 | 
			
		||||
        &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    test_context_deinit(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_get()
 | 
			
		||||
{
 | 
			
		||||
    test_run_in_context(&test_opt, test_get_run);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * list
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_list_run()
 | 
			
		||||
{
 | 
			
		||||
    TestContext test;
 | 
			
		||||
    const char* name = "name";
 | 
			
		||||
    char** list;
 | 
			
		||||
 | 
			
		||||
    test_context_init(&test);
 | 
			
		||||
 | 
			
		||||
    /* Request the list */
 | 
			
		||||
    list = gbinder_servicemanager_list_sync(test.client);
 | 
			
		||||
 | 
			
		||||
    /* There's nothing there yet */
 | 
			
		||||
    g_assert(list);
 | 
			
		||||
    g_assert(!list[0]);
 | 
			
		||||
    g_strfreev(list);
 | 
			
		||||
 | 
			
		||||
    /* Register object */
 | 
			
		||||
    GDEBUG("Registering object '%s' => %p", name, test.object);
 | 
			
		||||
    g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
 | 
			
		||||
        name, test.object), == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    /* Request the list again */
 | 
			
		||||
    list = gbinder_servicemanager_list_sync(test.client);
 | 
			
		||||
 | 
			
		||||
    /* Now the name must be there */
 | 
			
		||||
    g_assert_cmpuint(gutil_strv_length(list), == ,1);
 | 
			
		||||
    g_assert_cmpstr(list[0], == ,name);
 | 
			
		||||
    g_strfreev(list);
 | 
			
		||||
 | 
			
		||||
    test_context_deinit(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_list()
 | 
			
		||||
{
 | 
			
		||||
    test_run_in_context(&test_opt, test_list_run);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_(t) "/servicemanager_aidl4/" t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
 | 
			
		||||
    g_type_init();
 | 
			
		||||
    G_GNUC_END_IGNORE_DEPRECATIONS;
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("get"), test_get);
 | 
			
		||||
    g_test_add_func(TEST_("list"), test_list);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -82,6 +82,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 
 | 
			
		||||
@@ -240,6 +240,12 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -206,6 +206,12 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user