diff options
author | 2019-03-06 00:22:37 +0000 | |
---|---|---|
committer | 2019-03-06 00:22:37 +0000 | |
commit | 36415570df3c7f46ff3bd6f4f61abee66e4ff1dc (patch) | |
tree | 6c55381eae84143f69860cd4392a278b0a83b6ec | |
parent | 17f57c6ead2fe3f31b226feb0414b847142f4442 (diff) | |
parent | a194c456520b13779d00b313e0e969ba9a030525 (diff) |
Merge "libbinder_ndk: support dump"
-rw-r--r-- | libs/binder/ndk/ibinder.cpp | 61 | ||||
-rw-r--r-- | libs/binder/ndk/ibinder_internal.h | 6 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_ibinder.h | 40 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_interface_utils.h | 28 | ||||
-rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 2 |
5 files changed, 135 insertions, 2 deletions
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index f9c8c8a0ff..bdbc0d3b8b 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -31,6 +31,7 @@ using ::android::Parcel; using ::android::sp; using ::android::status_t; using ::android::String16; +using ::android::String8; using ::android::wp; namespace ABBinderTag { @@ -67,8 +68,6 @@ AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {} AIBinder::~AIBinder() {} bool AIBinder::associateClass(const AIBinder_Class* clazz) { - using ::android::String8; - if (clazz == nullptr) return false; if (mClazz == clazz) return true; @@ -119,6 +118,33 @@ const String16& ABBinder::getInterfaceDescriptor() const { return getClass()->getInterfaceDescriptor(); } +status_t ABBinder::dump(int fd, const ::android::Vector<String16>& args) { + AIBinder_onDump onDump = getClass()->onDump; + + if (onDump == nullptr) { + return STATUS_OK; + } + + // technically UINT32_MAX would be okay here, but INT32_MAX is expected since this may be + // null in Java + if (args.size() > INT32_MAX) { + LOG(ERROR) << "ABBinder::dump received too many arguments: " << args.size(); + return STATUS_BAD_VALUE; + } + + std::vector<String8> utf8Args; // owns memory of utf8s + utf8Args.reserve(args.size()); + std::vector<const char*> utf8Pointers; // what can be passed over NDK API + utf8Pointers.reserve(args.size()); + + for (size_t i = 0; i < args.size(); i++) { + utf8Args.push_back(String8(args[i])); + utf8Pointers.push_back(utf8Args[i].c_str()); + } + + return onDump(this, fd, utf8Pointers.data(), utf8Pointers.size()); +} + status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply, binder_flags_t flags) { if (isUserCommand(code)) { @@ -232,6 +258,13 @@ AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor, return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact); } +void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) { + CHECK(clazz != nullptr) << "setOnDump requires non-null clazz"; + + // this is required to be called before instances are instantiated + clazz->onDump = onDump; +} + void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) { CHECK(who == mWho); @@ -325,6 +358,30 @@ binder_status_t AIBinder_ping(AIBinder* binder) { return PruneStatusT(binder->getBinder()->pingBinder()); } +binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint32_t numArgs) { + if (binder == nullptr) { + return STATUS_UNEXPECTED_NULL; + } + + ABBinder* bBinder = binder->asABBinder(); + if (bBinder != nullptr) { + AIBinder_onDump onDump = binder->getClass()->onDump; + if (onDump == nullptr) { + return STATUS_OK; + } + return PruneStatusT(onDump(bBinder, fd, args, numArgs)); + } + + ::android::Vector<String16> utf16Args; + utf16Args.setCapacity(numArgs); + for (uint32_t i = 0; i < numArgs; i++) { + utf16Args.push(String16(String8(args[i]))); + } + + status_t status = binder->getBinder()->dump(fd, utf16Args); + return PruneStatusT(status); +} + binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { if (binder == nullptr || recipient == nullptr) { diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h index 7852298ef9..0dd795a676 100644 --- a/libs/binder/ndk/ibinder_internal.h +++ b/libs/binder/ndk/ibinder_internal.h @@ -25,6 +25,7 @@ #include <binder/Binder.h> #include <binder/IBinder.h> +#include <utils/Vector.h> inline bool isUserCommand(transaction_code_t code) { return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION; @@ -66,6 +67,7 @@ struct ABBinder : public AIBinder, public ::android::BBinder { ABBinder* asABBinder() override { return this; } const ::android::String16& getInterfaceDescriptor() const override; + ::android::status_t dump(int fd, const ::android::Vector<::android::String16>& args) override; ::android::status_t onTransact(uint32_t code, const ::android::Parcel& data, ::android::Parcel* reply, binder_flags_t flags) override; @@ -106,10 +108,14 @@ struct AIBinder_Class { const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; } + // required to be non-null, implemented for every class const AIBinder_Class_onCreate onCreate; const AIBinder_Class_onDestroy onDestroy; const AIBinder_Class_onTransact onTransact; + // optional methods for a class + AIBinder_onDump onDump; + private: // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to // one. diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index 9c6c55e736..bddc10de42 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -179,6 +179,31 @@ __attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define( __INTRODUCED_IN(29); /** + * Dump information about an AIBinder (usually for debugging). + * + * When no arguments are provided, a brief overview of the interview should be given. + * + * \param binder interface being dumped + * \param fd file descriptor to be dumped to, should be flushed, ownership is not passed. + * \param args array of null-terminated strings for dump (may be null if numArgs is 0) + * \param numArgs number of args to be sent + * + * \return binder_status_t result of transaction (if remote, for instance) + */ +typedef binder_status_t (*AIBinder_onDump)(AIBinder* binder, int fd, const char** args, + uint32_t numArgs); + +/** + * This sets the implementation of the dump method for a class. + * + * If this isn't set, nothing will be dumped when dump is called (for instance with + * android.os.Binder#dump). Must be called before any instance of the class is created. + * + * \param dump function to call when an instance of this binder class is being dumped. + */ +void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29); + +/** * Creates a new binder object of the appropriate class. * * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong @@ -237,6 +262,21 @@ bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29); binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29); /** + * Built-in transaction for all binder objects. This dumps information about a given binder. + * + * See also AIBinder_Class_setOnDump, AIBinder_onDump + * + * \param binder the binder to dump information about + * \param fd where information should be dumped to + * \param args null-terminated arguments to pass (may be null if numArgs is 0) + * \param numArgs number of args to send + * + * \return STATUS_OK if dump succeeds (or if there is nothing to dump) + */ +binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint32_t numArgs) + __INTRODUCED_IN(29); + +/** * Registers for notifications that the associated binder is dead. The same death recipient may be * associated with multiple different binders. If the binder is local, then no death recipient will * be given (since if the local process dies, then no recipient will exist to recieve a diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h index a42c60b5b2..b82141c932 100644 --- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h +++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h @@ -104,6 +104,30 @@ class ICInterface : public SharedRefBase { * this will be checked using AIBinder_isRemote. */ virtual bool isRemote() = 0; + + /** + * Dumps information about the interface. + */ + virtual binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) { + return STATUS_OK; + } + + /** + * Helper method to create a class + */ + static AIBinder_Class* defineClass(const char* interfaceDescriptor, + AIBinder_Class_onCreate onCreate, + AIBinder_Class_onDestroy onDestroy, + AIBinder_Class_onTransact onTransact, + AIBinder_onDump onDump = nullptr) { + AIBinder_Class* clazz = + AIBinder_Class_define(interfaceDescriptor, onCreate, onDestroy, onTransact); + if (clazz == nullptr) { + return nullptr; + } + AIBinder_Class_setOnDump(clazz, onDump); + return clazz; + } }; /** @@ -144,6 +168,10 @@ class BpCInterface : public INTERFACE { bool isRemote() override { return AIBinder_isRemote(mBinder.get()); } + binder_status_t dump(int fd, const char** args, uint32_t numArgs) override { + return AIBinder_dump(asBinder().get(), fd, args, numArgs); + } + private: SpAIBinder mBinder; }; diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 655f4d50aa..7e6581736f 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -2,10 +2,12 @@ LIBBINDER_NDK { # introduced=29 global: AIBinder_associateClass; AIBinder_Class_define; + AIBinder_Class_setOnDump; AIBinder_DeathRecipient_delete; AIBinder_DeathRecipient_new; AIBinder_debugGetRefCount; AIBinder_decStrong; + AIBinder_dump; AIBinder_fromJavaBinder; AIBinder_getCallingPid; AIBinder_getCallingUid; |