mirror of https://github.com/grpc/grpc.git
[BinderTransport] Avoid depending on NdkBinder at compile time (#27912)
* [BinderTransport] Avoid depending on NdkBinder at compile time We would like to make it possible to use BinderTransport in a APK that has min sdk version lower than 29 (NdkBinder was introduced at 29) We copies constants and type definitions from Ndk headers, creates a same name wrapper for every NdkBinder API we use in grpc_binder::ndk_util namespace. We will try to load libbinder_ndk.so and resolve the symbol when the NdkBinder API wrappers are invoked. * regenerate projects * Add GRPC_NO_BINDER guardpull/27944/head
parent
577d799de0
commit
5c0df85ea8
20 changed files with 477 additions and 138 deletions
@ -0,0 +1,76 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_BINDER_AUTO_UTILS_H |
||||
#define GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_BINDER_AUTO_UTILS_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GPR_SUPPORT_BINDER_TRANSPORT |
||||
|
||||
#include "src/core/ext/transport/binder/utils/ndk_binder.h" |
||||
|
||||
namespace grpc_binder { |
||||
namespace ndk_util { |
||||
|
||||
/**
|
||||
* Represents one strong pointer to an AIBinder object. |
||||
* Copied from binder/ndk/include_cpp/android/binder_auto_utils.h |
||||
*/ |
||||
class SpAIBinder { |
||||
public: |
||||
SpAIBinder() : mBinder(nullptr) {} |
||||
explicit SpAIBinder(AIBinder* binder) : mBinder(binder) {} |
||||
SpAIBinder(std::nullptr_t) |
||||
: SpAIBinder() {} // NOLINT(google-explicit-constructor)
|
||||
SpAIBinder(const SpAIBinder& other) { *this = other; } |
||||
|
||||
~SpAIBinder() { set(nullptr); } |
||||
SpAIBinder& operator=(const SpAIBinder& other) { |
||||
if (this == &other) { |
||||
return *this; |
||||
} |
||||
AIBinder_incStrong(other.mBinder); |
||||
set(other.mBinder); |
||||
return *this; |
||||
} |
||||
|
||||
void set(AIBinder* binder) { |
||||
AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder); |
||||
if (old != nullptr) AIBinder_decStrong(old); |
||||
if (old != *const_cast<AIBinder* volatile*>(&mBinder)) { |
||||
__assert(__FILE__, __LINE__, "Race detected."); |
||||
} |
||||
mBinder = binder; |
||||
} |
||||
|
||||
AIBinder* get() const { return mBinder; } |
||||
AIBinder** getR() { return &mBinder; } |
||||
|
||||
bool operator!=(const SpAIBinder& rhs) const { return get() != rhs.get(); } |
||||
bool operator<(const SpAIBinder& rhs) const { return get() < rhs.get(); } |
||||
bool operator<=(const SpAIBinder& rhs) const { return get() <= rhs.get(); } |
||||
bool operator==(const SpAIBinder& rhs) const { return get() == rhs.get(); } |
||||
bool operator>(const SpAIBinder& rhs) const { return get() > rhs.get(); } |
||||
bool operator>=(const SpAIBinder& rhs) const { return get() >= rhs.get(); } |
||||
|
||||
private: |
||||
AIBinder* mBinder = nullptr; |
||||
}; |
||||
} // namespace ndk_util
|
||||
} // namespace grpc_binder
|
||||
|
||||
#endif |
||||
|
||||
#endif // GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_BINDER_AUTO_UTILS_H
|
@ -0,0 +1,165 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/transport/binder/utils/ndk_binder.h" |
||||
|
||||
#ifndef GRPC_NO_BINDER |
||||
|
||||
#ifdef GPR_SUPPORT_BINDER_TRANSPORT |
||||
|
||||
#include <dlfcn.h> |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
namespace { |
||||
void* GetNdkBinderHandle() { |
||||
// TODO(mingcl): Consider using RTLD_NOLOAD to check if it is already loaded
|
||||
// first
|
||||
static void* handle = dlopen("libbinder_ndk.so", RTLD_LAZY); |
||||
if (handle == nullptr) { |
||||
gpr_log( |
||||
GPR_ERROR, |
||||
"Cannot open libbinder_ndk.so. Does this device support API level 29?"); |
||||
GPR_ASSERT(0); |
||||
} |
||||
return handle; |
||||
} |
||||
} // namespace
|
||||
|
||||
namespace grpc_binder { |
||||
namespace ndk_util { |
||||
|
||||
// Helper macro to obtain the function pointer corresponding to the name
|
||||
#define FORWARD(name) \ |
||||
typedef decltype(&name) func_type; \
|
||||
static func_type ptr = \
|
||||
reinterpret_cast<func_type>(dlsym(GetNdkBinderHandle(), #name)); \
|
||||
if (ptr == nullptr) { \
|
||||
gpr_log(GPR_ERROR, \
|
||||
"dlsym failed. Cannot find %s in libbinder_ndk.so. " \
|
||||
"BinderTransport requires API level >= 33", \
|
||||
#name); \ |
||||
GPR_ASSERT(0); \
|
||||
} \
|
||||
return ptr |
||||
|
||||
void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) { |
||||
FORWARD(AIBinder_Class_disableInterfaceTokenHeader)(clazz); |
||||
} |
||||
|
||||
void* AIBinder_getUserData(AIBinder* binder) { |
||||
FORWARD(AIBinder_getUserData)(binder); |
||||
} |
||||
|
||||
uid_t AIBinder_getCallingUid() { FORWARD(AIBinder_getCallingUid)(); } |
||||
|
||||
AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) { |
||||
FORWARD(AIBinder_fromJavaBinder)(env, binder); |
||||
} |
||||
|
||||
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor, |
||||
AIBinder_Class_onCreate onCreate, |
||||
AIBinder_Class_onDestroy onDestroy, |
||||
AIBinder_Class_onTransact onTransact) { |
||||
FORWARD(AIBinder_Class_define) |
||||
(interfaceDescriptor, onCreate, onDestroy, onTransact); |
||||
} |
||||
|
||||
AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) { |
||||
FORWARD(AIBinder_new)(clazz, args); |
||||
} |
||||
|
||||
bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) { |
||||
FORWARD(AIBinder_associateClass)(binder, clazz); |
||||
} |
||||
|
||||
void AIBinder_incStrong(AIBinder* binder) { |
||||
FORWARD(AIBinder_incStrong)(binder); |
||||
} |
||||
|
||||
void AIBinder_decStrong(AIBinder* binder) { |
||||
FORWARD(AIBinder_decStrong)(binder); |
||||
} |
||||
|
||||
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, |
||||
AParcel** in, AParcel** out, |
||||
binder_flags_t flags) { |
||||
FORWARD(AIBinder_transact)(binder, code, in, out, flags); |
||||
} |
||||
|
||||
binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData, |
||||
AParcel_byteArrayAllocator allocator) { |
||||
FORWARD(AParcel_readByteArray)(parcel, arrayData, allocator); |
||||
} |
||||
|
||||
void AParcel_delete(AParcel* parcel) { FORWARD(AParcel_delete)(parcel); } |
||||
int32_t AParcel_getDataSize(const AParcel* parcel) { |
||||
FORWARD(AParcel_getDataSize)(parcel); |
||||
} |
||||
|
||||
binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) { |
||||
FORWARD(AParcel_writeInt32)(parcel, value); |
||||
} |
||||
|
||||
binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) { |
||||
FORWARD(AParcel_writeInt64)(parcel, value); |
||||
} |
||||
|
||||
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) { |
||||
FORWARD(AParcel_writeStrongBinder)(parcel, binder); |
||||
} |
||||
|
||||
binder_status_t AParcel_writeString(AParcel* parcel, const char* string, |
||||
int32_t length) { |
||||
FORWARD(AParcel_writeString)(parcel, string, length); |
||||
} |
||||
|
||||
binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) { |
||||
FORWARD(AParcel_readInt32)(parcel, value); |
||||
} |
||||
|
||||
binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) { |
||||
FORWARD(AParcel_readInt64)(parcel, value); |
||||
} |
||||
|
||||
binder_status_t AParcel_readString(const AParcel* parcel, void* stringData, |
||||
AParcel_stringAllocator allocator) { |
||||
FORWARD(AParcel_readString)(parcel, stringData, allocator); |
||||
} |
||||
|
||||
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, |
||||
AIBinder** binder) { |
||||
FORWARD(AParcel_readStrongBinder)(parcel, binder); |
||||
} |
||||
|
||||
binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, |
||||
int32_t length) { |
||||
FORWARD(AParcel_writeByteArray)(parcel, arrayData, length); |
||||
} |
||||
|
||||
binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) { |
||||
FORWARD(AIBinder_prepareTransaction)(binder, in); |
||||
} |
||||
|
||||
jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) { |
||||
FORWARD(AIBinder_toJavaBinder)(env, binder); |
||||
} |
||||
|
||||
} // namespace ndk_util
|
||||
} // namespace grpc_binder
|
||||
|
||||
#endif |
||||
#endif |
@ -0,0 +1,107 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_NDK_BINDER_H |
||||
#define GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_NDK_BINDER_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GPR_SUPPORT_BINDER_TRANSPORT |
||||
|
||||
#include <assert.h> |
||||
#include <jni.h> |
||||
|
||||
#include <memory> |
||||
|
||||
// This file defines NdkBinder functions, variables, and types in
|
||||
// ::grpc_binder::ndk_util namespace. This allows us to dynamically load
|
||||
// libbinder_ndk at runtime, and make it possible to compile the code without
|
||||
// the library present at compile time.
|
||||
|
||||
// TODO(mingcl): Consider if we want to check API level and include NDK headers
|
||||
// normally if the level is high enough
|
||||
|
||||
namespace grpc_binder { |
||||
namespace ndk_util { |
||||
|
||||
struct AIBinder; |
||||
struct AParcel; |
||||
struct AIBinder_Class; |
||||
|
||||
// Only enum values used by the project is defined here
|
||||
enum { |
||||
FLAG_ONEWAY = 0x01, |
||||
}; |
||||
enum { |
||||
STATUS_OK = 0, |
||||
STATUS_UNKNOWN_ERROR = (-2147483647 - 1), |
||||
}; |
||||
|
||||
typedef int32_t binder_status_t; |
||||
typedef uint32_t binder_flags_t; |
||||
typedef uint32_t transaction_code_t; |
||||
|
||||
typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, |
||||
int8_t** outBuffer); |
||||
typedef bool (*AParcel_stringAllocator)(void* stringData, int32_t length, |
||||
char** buffer); |
||||
typedef void* (*AIBinder_Class_onCreate)(void* args); |
||||
typedef void (*AIBinder_Class_onDestroy)(void* userData); |
||||
typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, |
||||
transaction_code_t code, |
||||
const AParcel* in, |
||||
AParcel* out); |
||||
|
||||
void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz); |
||||
void* AIBinder_getUserData(AIBinder* binder); |
||||
uid_t AIBinder_getCallingUid(); |
||||
AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder); |
||||
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor, |
||||
AIBinder_Class_onCreate onCreate, |
||||
AIBinder_Class_onDestroy onDestroy, |
||||
AIBinder_Class_onTransact onTransact); |
||||
AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args); |
||||
bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz); |
||||
void AIBinder_incStrong(AIBinder* binder); |
||||
void AIBinder_decStrong(AIBinder* binder); |
||||
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, |
||||
AParcel** in, AParcel** out, |
||||
binder_flags_t flags); |
||||
binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData, |
||||
AParcel_byteArrayAllocator allocator); |
||||
void AParcel_delete(AParcel* parcel); |
||||
int32_t AParcel_getDataSize(const AParcel* parcel); |
||||
binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value); |
||||
binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value); |
||||
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder); |
||||
binder_status_t AParcel_writeString(AParcel* parcel, const char* string, |
||||
int32_t length); |
||||
binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value); |
||||
binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value); |
||||
binder_status_t AParcel_readString(const AParcel* parcel, void* stringData, |
||||
AParcel_stringAllocator allocator); |
||||
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, |
||||
AIBinder** binder); |
||||
binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, |
||||
int32_t length); |
||||
binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in); |
||||
jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder); |
||||
|
||||
} // namespace ndk_util
|
||||
|
||||
} // namespace grpc_binder
|
||||
|
||||
#endif /*GPR_SUPPORT_BINDER_TRANSPORT*/ |
||||
|
||||
#endif // GRPC_CORE_EXT_TRANSPORT_BINDER_UTILS_NDK_BINDER_H
|
Loading…
Reference in new issue