Merge pull request #83 from adglkh/api_31_support
[gbinder] Support for Android 12 (API level 31). JB#42254
This commit is contained in:
1
Makefile
1
Makefile
@@ -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 += \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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,17 @@ 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 */
|
||||
gbinder_config_exit();
|
||||
g_assert_cmpint(remove(file1), == ,0);
|
||||
g_assert_cmpint(remove(file2), == ,0);
|
||||
g_assert_cmpint(remove(file3), == ,0);
|
||||
g_assert_cmpint(remove(file4), == ,0);
|
||||
g_assert(!gbinder_config_get());
|
||||
|
||||
/* Undo all the damage */
|
||||
@@ -329,6 +345,7 @@ test_dirs(
|
||||
g_free(file1);
|
||||
g_free(file2);
|
||||
g_free(file3);
|
||||
g_free(file4);
|
||||
g_free(random_file);
|
||||
|
||||
remove(notafile);
|
||||
@@ -495,6 +512,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