blob: 638c93c5402f383ab5c413c04e51f6411877926a [file] [log] [blame]
// 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/client/endpoint_binder_pool.h"
#ifndef GRPC_NO_BINDER
#include "src/core/ext/transport/binder/client/jni_utils.h"
#ifdef GPR_SUPPORT_BINDER_TRANSPORT
#include <jni.h>
#include "src/core/ext/transport/binder/wire_format/binder_android.h"
extern "C" {
// Adds endpoint binder to binder pool when Java notify us that the endpoint
// binder is ready. This is called from GrpcBinderConnection.java
JNIEXPORT void JNICALL
Java_io_grpc_binder_cpp_GrpcBinderConnection_notifyConnected__Ljava_lang_String_2Landroid_os_IBinder_2(
JNIEnv* jni_env, jobject, jstring conn_id_jstring, jobject ibinder) {
jboolean isCopy;
const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
gpr_log(GPR_ERROR, "%s called with conn_id = %s", __func__, conn_id);
GPR_ASSERT(ibinder != nullptr);
grpc_binder::ndk_util::SpAIBinder aibinder =
grpc_binder::FromJavaBinder(jni_env, ibinder);
gpr_log(GPR_ERROR, "aibinder = %p", aibinder.get());
auto b = absl::make_unique<grpc_binder::BinderAndroid>(aibinder);
GPR_ASSERT(b != nullptr);
grpc_binder::GetEndpointBinderPool()->AddEndpointBinder(conn_id,
std::move(b));
if (isCopy == JNI_TRUE) {
jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
}
}
}
#endif // GPR_SUPPORT_BINDER_TRANSPORT
namespace grpc_binder {
void EndpointBinderPool ::GetEndpointBinder(
std::string conn_id,
std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb) {
gpr_log(GPR_ERROR, "GetEndpointBinder %s", conn_id.c_str());
std::unique_ptr<grpc_binder::Binder> b;
{
grpc_core::MutexLock l(&m_);
if (binder_map_.count(conn_id)) {
b = std::move(binder_map_[conn_id]);
binder_map_.erase(conn_id);
GPR_ASSERT(b != nullptr);
} else {
if (pending_requests_.count(conn_id) != 0) {
gpr_log(GPR_ERROR, "Duplicate GetEndpointBinder request. conn_id = %s",
conn_id.c_str());
return;
}
pending_requests_[conn_id] = std::move(cb);
return;
}
}
GPR_ASSERT(b != nullptr);
cb(std::move(b));
}
void EndpointBinderPool::AddEndpointBinder(
std::string conn_id, std::unique_ptr<grpc_binder::Binder> b) {
gpr_log(GPR_ERROR, "AddEndpointBinder %s", conn_id.c_str());
GPR_ASSERT(b != nullptr);
// cb will be set in the following block if there is a pending callback
std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb = nullptr;
{
grpc_core::MutexLock l(&m_);
if (binder_map_.count(conn_id) != 0) {
gpr_log(GPR_ERROR, "EndpointBinder already in the pool. conn_id = %s",
conn_id.c_str());
return;
}
if (pending_requests_.count(conn_id)) {
cb = std::move(pending_requests_[conn_id]);
pending_requests_.erase(conn_id);
} else {
binder_map_[conn_id] = std::move(b);
b = nullptr;
}
}
if (cb != nullptr) {
cb(std::move(b));
}
}
EndpointBinderPool* GetEndpointBinderPool() {
static EndpointBinderPool* p = new EndpointBinderPool();
return p;
}
} // namespace grpc_binder
#endif