diff options
author | 2022-07-27 15:54:06 +0000 | |
---|---|---|
committer | 2022-08-18 22:41:57 +0000 | |
commit | 3faaa0005ba96daac7400693a6a5f03a18ec41be (patch) | |
tree | b83042cbef9d3bb36973e6e2e2c9a24380632d90 | |
parent | fc20cdf533b63de60923712b57c535f540c754b4 (diff) |
Add lookupOrCreateWeak to ObjectManager
This looks for an attached object on the binder, attempts to promote it,
and returns the object if it could be promoted.
Otherwise, it will create a new object and attach it to the binder.
Test: atest binderUnitTest aidl_integration_test
Bug: 220141324
Change-Id: I2c8baa211300fa3ada50f2b2c93862f8c968be26
-rw-r--r-- | libs/binder/Binder.cpp | 19 | ||||
-rw-r--r-- | libs/binder/BpBinder.cpp | 36 | ||||
-rw-r--r-- | libs/binder/include/binder/Binder.h | 2 | ||||
-rw-r--r-- | libs/binder/include/binder/BpBinder.h | 10 | ||||
-rw-r--r-- | libs/binder/include/binder/IBinder.h | 3 | ||||
-rw-r--r-- | libs/binder/tests/binderBinderUnitTest.cpp | 49 |
6 files changed, 115 insertions, 4 deletions
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index b5ea60f102..1dc62334cb 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -202,6 +202,17 @@ void IBinder::withLock(const std::function<void()>& doWithLock) { proxy->withLock(doWithLock); } +sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func make, + const void* makeArgs) { + BBinder* local = localBinder(); + if (local) { + return local->lookupOrCreateWeak(objectID, make, makeArgs); + } + BpBinder* proxy = this->remoteBinder(); + LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote"); + return proxy->lookupOrCreateWeak(objectID, make, makeArgs); +} + // --------------------------------------------------------------------------- class BBinder::RpcServerLink : public IBinder::DeathRecipient { @@ -378,6 +389,14 @@ void BBinder::withLock(const std::function<void()>& doWithLock) { doWithLock(); } +sp<IBinder> BBinder::lookupOrCreateWeak(const void* objectID, object_make_func make, + const void* makeArgs) { + Extras* e = getOrCreateExtras(); + LOG_ALWAYS_FATAL_IF(!e, "no memory"); + AutoMutex _l(e->mLock); + return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs); +} + BBinder* BBinder::localBinder() { return this; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index b6d35ef3ef..d9b723108e 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -100,6 +100,36 @@ void* BpBinder::ObjectManager::detach(const void* objectID) { return value; } +namespace { +struct Tag { + wp<IBinder> binder; +}; +} // namespace + +static void cleanWeak(const void* /* id */, void* obj, void* /* cookie */) { + delete static_cast<Tag*>(obj); +} + +sp<IBinder> BpBinder::ObjectManager::lookupOrCreateWeak(const void* objectID, object_make_func make, + const void* makeArgs) { + entry_t& e = mObjects[objectID]; + if (e.object != nullptr) { + if (auto attached = static_cast<Tag*>(e.object)->binder.promote()) { + return attached; + } + } else { + e.object = new Tag; + LOG_ALWAYS_FATAL_IF(!e.object, "no more memory"); + } + sp<IBinder> newObj = make(makeArgs); + + static_cast<Tag*>(e.object)->binder = newObj; + e.cleanupCookie = nullptr; + e.func = cleanWeak; + + return newObj; +} + void BpBinder::ObjectManager::kill() { const size_t N = mObjects.size(); @@ -516,6 +546,12 @@ void BpBinder::withLock(const std::function<void()>& doWithLock) { doWithLock(); } +sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make, + const void* makeArgs) { + AutoMutex _l(mLock); + return mObjects.lookupOrCreateWeak(objectID, make, makeArgs); +} + BpBinder* BpBinder::remoteBinder() { return this; diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index 46223bb00e..88d9ca1d58 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -59,6 +59,8 @@ public: virtual void* findObject(const void* objectID) const final; virtual void* detachObject(const void* objectID) final; void withLock(const std::function<void()>& doWithLock); + sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make, + const void* makeArgs); virtual BBinder* localBinder(); diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 19ad5e6efe..4172cc511e 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -72,6 +72,8 @@ public: virtual void* findObject(const void* objectID) const final; virtual void* detachObject(const void* objectID) final; void withLock(const std::function<void()>& doWithLock); + sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make, + const void* makeArgs); virtual BpBinder* remoteBinder(); @@ -96,6 +98,8 @@ public: IBinder::object_cleanup_func func); void* find(const void* objectID) const; void* detach(const void* objectID); + sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make, + const void* makeArgs); void kill(); @@ -104,9 +108,9 @@ public: ObjectManager& operator=(const ObjectManager&); struct entry_t { - void* object; - void* cleanupCookie; - IBinder::object_cleanup_func func; + void* object = nullptr; + void* cleanupCookie = nullptr; + IBinder::object_cleanup_func func = nullptr; }; std::map<const void*, entry_t> mObjects; diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index 43fc5ff1a9..83aaca7f95 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -284,6 +284,9 @@ public: virtual BBinder* localBinder(); virtual BpBinder* remoteBinder(); + typedef sp<IBinder> (*object_make_func)(const void* makeArgs); + sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make, + const void* makeArgs); protected: virtual ~IBinder(); diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp index ce2770f943..b6aed0db28 100644 --- a/libs/binder/tests/binderBinderUnitTest.cpp +++ b/libs/binder/tests/binderBinderUnitTest.cpp @@ -15,10 +15,11 @@ */ #include <binder/Binder.h> -#include <binder/IBinder.h> +#include <binder/IInterface.h> #include <gtest/gtest.h> using android::BBinder; +using android::IBinder; using android::OK; using android::sp; @@ -48,3 +49,49 @@ TEST(Binder, AttachExtension) { binder->setExtension(ext); EXPECT_EQ(ext, binder->getExtension()); } + +struct MyCookie { + bool* deleted; +}; + +class UniqueBinder : public BBinder { +public: + UniqueBinder(const void* c) : cookie(reinterpret_cast<const MyCookie*>(c)) { + *cookie->deleted = false; + } + ~UniqueBinder() { *cookie->deleted = true; } + const MyCookie* cookie; +}; + +static sp<IBinder> make(const void* arg) { + return sp<UniqueBinder>::make(arg); +} + +TEST(Binder, LookupOrCreateWeak) { + auto binder = sp<BBinder>::make(); + bool deleted; + MyCookie cookie = {&deleted}; + sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie); + EXPECT_NE(binder, createdBinder); + + sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie); + EXPECT_EQ(createdBinder, lookedUpBinder); + EXPECT_FALSE(deleted); +} + +TEST(Binder, LookupOrCreateWeakDropSp) { + auto binder = sp<BBinder>::make(); + bool deleted1 = false; + bool deleted2 = false; + MyCookie cookie1 = {&deleted1}; + MyCookie cookie2 = {&deleted2}; + sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie1); + EXPECT_NE(binder, createdBinder); + + createdBinder.clear(); + EXPECT_TRUE(deleted1); + + sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie2); + EXPECT_EQ(&cookie2, sp<UniqueBinder>::cast(lookedUpBinder)->cookie); + EXPECT_FALSE(deleted2); +} |