libbinder: extension mechanism for all binders
See IBinder::getExtension in this CL for how to use this functionality,
this message only explains background/motivation.
This gives a generic way to extend (actually compose) binder interfaces
for downstream codebases. For instance, INetd.aidl has the API "IBinder
getOemNetd();" which allows someone to extend the INetd interface.
However, adding this manually to interfaces has two problems:
- it requires manaul effort by the maintainer
- we don't know who will extend which interfaces should be extended
(this is what justifies adding this extension mechanism in general)
* Fundamental problem these extensions solve:
In Android, there is a very common problem:
- year 1: AOSP maintainer adds interface
- year 1.5: downstream maintainer modifies interface to add
additional features
- year 2: AOSP maintainer modifies interface
PAIN - year 2.5: downstream maintainer must rebase PAIN
In order to avoid these rebases/merge conflicts in downstream trees,
this mechanism provides a generic way to extend the functionality of
an interface.
This same problem also occurs through chains of downstream
maintainers (perhaps the same interface will be changed many many
times in further downstream branches).
* Other attempts at addressing things (a.k.a. why composition):
HIDL solves this problem via inheritance, but we don't want to port
this to be in AIDL:
- single inheritance is not enough (would need multiple
inheritance).
For instance if we have downstream@1.0::IFoo extends
upstream@1.0::IFoo, if upstream adds upstream@1.1::IFoo (which
by convention extends upstream@1.0::IFoo), then downstream must
rebase their interface to have downstream@2.0::IFoo extends
upstream@1.1::IFoo.
- multiple inheritance is really messy
Bug: 136027762
Test: binderLibTest
Change-Id: Ifa6d228e47df3857421ac452c188be225bb16016
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 4f0c969..5f8887b 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -766,6 +766,24 @@
EXPECT_TRUE(strong_from_weak == nullptr);
}
+TEST_F(BinderLibTest, LocalGetExtension) {
+ sp<BBinder> binder = new BBinder();
+ sp<IBinder> ext = new BBinder();
+ binder->setExtension(ext);
+ EXPECT_EQ(ext, binder->getExtension());
+}
+
+TEST_F(BinderLibTest, RemoteGetExtension) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ sp<IBinder> extension;
+ EXPECT_EQ(NO_ERROR, server->getExtension(&extension));
+ ASSERT_NE(nullptr, extension.get());
+
+ EXPECT_EQ(NO_ERROR, extension->pingBinder());
+}
+
TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
status_t ret;
Parcel data, reply;
@@ -1170,6 +1188,13 @@
BinderLibTestService* testServicePtr;
{
sp<BinderLibTestService> testService = new BinderLibTestService(index);
+
+ /*
+ * Normally would also contain functionality as well, but we are only
+ * testing the extension mechanism.
+ */
+ testService->setExtension(new BBinder());
+
/*
* We need this below, but can't hold a sp<> because it prevents the
* node from being cleaned up automatically. It's safe in this case