diff options
author | Steven Moreland <smoreland@google.com> | 2019-08-20 10:50:08 -0700 |
---|---|---|
committer | Steven Moreland <smoreland@google.com> | 2019-08-20 11:40:37 -0700 |
commit | ea14ef2629eb1ad16a6bc09608614f80489d36c4 (patch) | |
tree | 8bca68c127d2a58088fd47e470908ac99a09a651 | |
parent | f8fb40c0cfca59b4f459d76226c397cef6186d3b (diff) | |
download | native-ea14ef2629eb1ad16a6bc09608614f80489d36c4.tar.gz |
libbinder_ndk: set/getExtension
Similar to what is on IBinder. See comment on AIBinder_setExtension for
detailed information on usage.
This allows downstream codebases to tag on data to binders for their
extensions rather than having to modify the interface directly (which
breaks ABI compatibility and may cause more merge conflicts).
Bug: 136027762
Test: atest CtsNdkBinderTestCases
Change-Id: I2d1bb6cd906ff1974df8e81475d5fa8f569e9b6e
-rw-r--r-- | libs/binder/ndk/ibinder.cpp | 37 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_ibinder.h | 70 | ||||
-rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 3 |
3 files changed, 110 insertions, 0 deletions
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index bd6886d1ee..b06ca86f57 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -589,3 +589,40 @@ void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) { recipient->decStrong(nullptr); } + +binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) { + if (binder == nullptr || outExt == nullptr) { + if (outExt != nullptr) { + *outExt = nullptr; + } + return STATUS_UNEXPECTED_NULL; + } + + sp<IBinder> ext; + status_t res = binder->getBinder()->getExtension(&ext); + + if (res != android::OK) { + *outExt = nullptr; + return PruneStatusT(res); + } + + sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(ext); + if (ret != nullptr) ret->incStrong(binder); + + *outExt = ret.get(); + return STATUS_OK; +} + +binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) { + if (binder == nullptr || ext == nullptr) { + return STATUS_UNEXPECTED_NULL; + } + + ABBinder* rawBinder = binder->asABBinder(); + if (rawBinder == nullptr) { + return STATUS_INVALID_OPERATION; + } + + rawBinder->setExtension(ext->getBinder()); + return STATUS_OK; +} diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index 80d12541be..160739b044 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -510,6 +510,76 @@ __attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecip void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29); #endif //__ANDROID_API__ >= __ANDROID_API_Q__ + +#if __ANDROID_API__ >= __ANDROID_API_R__ + +/** + * Gets the extension registered with AIBinder_setExtension. + * + * See AIBinder_setExtension. + * + * \param binder the object to get the extension of. + * \param outExt the returned extension object. Will be null if there is no extension set or + * non-null with one strong ref count. + * + * \return error of getting the interface (may be a transaction error if this is + * remote binder). STATUS_UNEXPECTED_NULL if binder is null. + */ +binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INTRODUCED_IN(30); + +/** + * Gets the extension of a binder interface. This allows a downstream developer to add + * an extension to an interface without modifying its interface file. This should be + * called immediately when the object is created before it is passed to another thread. + * No thread safety is required. + * + * For instance, imagine if we have this interface: + * interface IFoo { void doFoo(); } + * + * A). Historical option that has proven to be BAD! Only the original + * author of an interface should change an interface. If someone + * downstream wants additional functionality, they should not ever + * change the interface or use this method. + * + * BAD TO DO: interface IFoo { BAD TO DO + * BAD TO DO: void doFoo(); BAD TO DO + * BAD TO DO: + void doBar(); // adding a method BAD TO DO + * BAD TO DO: } BAD TO DO + * + * B). Option that this method enables. + * Leave the original interface unchanged (do not change IFoo!). + * Instead, create a new interface in a downstream package: + * + * package com.<name>; // new functionality in a new package + * interface IBar { void doBar(); } + * + * When registering the interface, add: + * std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase + * std::shared_ptr<MyBar> bar = new MyBar; // custom extension class + * ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get()); + * // handle error + * + * Then, clients of IFoo can get this extension: + * SpAIBinder binder = ...; + * std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null + * SpAIBinder barBinder; + * ... = AIBinder_getExtension(barBinder.get()); + * // handle error + * std::shared_ptr<IBar> bar = IBar::fromBinder(barBinder); + * // type is checked with AIBinder_associateClass + * // if bar is null, then there is no extension or a different + * // type of extension + * + * \param binder the object to get the extension on. Must be local. + * \param ext the extension to set (binder will hold a strong reference to this) + * + * \return OK on success, STATUS_INVALID_OPERATION if binder is not local, STATUS_UNEXPECTED_NULL + * if either binder is null. + */ +binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30); + +#endif //__ANDROID_API__ >= __ANDROID_API_R__ + __END_DECLS /** @} */ diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index feedde6b86..d4d5387f33 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -101,6 +101,9 @@ LIBBINDER_NDK { # introduced=29 LIBBINDER_NDK30 { # introduced=30 global: + AIBinder_getExtension; + AIBinder_setExtension; + AIBinder_markSystemStability; # apex AIBinder_markVendorStability; # vndk AIBinder_markVintfStability; # apex vndk |