diff options
| author | 2019-08-21 17:53:27 +0000 | |
|---|---|---|
| committer | 2019-08-21 17:53:27 +0000 | |
| commit | c176c0da5f82a5e7d7255ee833857eb2562aecea (patch) | |
| tree | bb6f51039dca08bc3d1526b5f6c5e681fa133707 | |
| parent | 267b36b7d03663a0e3e16044469fbced2825a2b8 (diff) | |
| parent | ea14ef2629eb1ad16a6bc09608614f80489d36c4 (diff) | |
Merge "libbinder_ndk: set/getExtension"
| -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 |