1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <grpc/support/port_platform.h>
16 
17 #ifndef GRPC_NO_BINDER
18 
19 #include <grpcpp/create_channel_binder.h>
20 
21 // The interface is only defined if GPR_ANDROID is defined, because some
22 // arguments requires JNI.
23 // Furthermore, the interface is non-phony only when
24 // GPR_SUPPORT_BINDER_TRANSPORT is true because actual implementation of binder
25 // transport requires newer version of NDK API
26 
27 #ifdef GPR_ANDROID
28 
29 #include <grpc/grpc.h>
30 #include <grpc/grpc_posix.h>
31 #include <grpc/support/log.h>
32 
33 #include "src/core/lib/gprpp/crash.h"
34 
35 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
36 
37 #include <grpc/support/port_platform.h>
38 
39 #include "absl/memory/memory.h"
40 #include "absl/strings/substitute.h"
41 #include "absl/time/clock.h"
42 #include "absl/time/time.h"
43 
44 #include <grpcpp/impl/grpc_library.h>
45 
46 #include "src/core/ext/filters/client_channel/client_channel.h"
47 #include "src/core/ext/transport/binder/client/channel_create_impl.h"
48 #include "src/core/ext/transport/binder/client/connection_id_generator.h"
49 #include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
50 #include "src/core/ext/transport/binder/client/jni_utils.h"
51 #include "src/core/ext/transport/binder/client/security_policy_setting.h"
52 #include "src/core/ext/transport/binder/transport/binder_transport.h"
53 #include "src/core/ext/transport/binder/wire_format/binder.h"
54 #include "src/core/ext/transport/binder/wire_format/binder_android.h"
55 #include "src/core/lib/channel/channel_args.h"
56 #include "src/core/lib/config/core_configuration.h"
57 #include "src/core/lib/surface/channel.h"
58 #include "src/core/lib/transport/transport.h"
59 #include "src/cpp/client/create_channel_internal.h"
60 
61 namespace {
62 // grpc.io.action.BIND is the standard action name for binding to binder
63 // transport server.
64 const char* kStandardActionName = "grpc.io.action.BIND";
65 }  // namespace
66 
67 namespace grpc {
68 namespace experimental {
69 
CreateBinderChannel(void * jni_env_void,jobject context,absl::string_view package_name,absl::string_view class_name,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)70 std::shared_ptr<grpc::Channel> CreateBinderChannel(
71     void* jni_env_void, jobject context, absl::string_view package_name,
72     absl::string_view class_name,
73     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
74         security_policy) {
75   return CreateCustomBinderChannel(jni_env_void, context, package_name,
76                                    class_name, security_policy,
77                                    ChannelArguments());
78 }
79 
CreateCustomBinderChannel(void * jni_env_void,jobject context,absl::string_view package_name,absl::string_view class_name,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,const ChannelArguments & args)80 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
81     void* jni_env_void, jobject context, absl::string_view package_name,
82     absl::string_view class_name,
83     std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
84     const ChannelArguments& args) {
85   return CreateCustomBinderChannel(
86       jni_env_void, context,
87       absl::Substitute("android-app://$0#Intent;action=$1;component=$0/$2;end",
88                        package_name, kStandardActionName, class_name),
89       security_policy, args);
90 }
91 
CreateBinderChannel(void * jni_env_void,jobject context,absl::string_view uri,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)92 std::shared_ptr<grpc::Channel> CreateBinderChannel(
93     void* jni_env_void, jobject context, absl::string_view uri,
94     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
95         security_policy) {
96   return CreateCustomBinderChannel(jni_env_void, context, uri, security_policy,
97                                    ChannelArguments());
98 }
99 
CreateCustomBinderChannel(void * jni_env_void,jobject context,absl::string_view uri,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,const ChannelArguments & args)100 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
101     void* jni_env_void, jobject context, absl::string_view uri,
102     std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
103     const ChannelArguments& args) {
104   grpc_init();
105 
106   GPR_ASSERT(jni_env_void != nullptr);
107   GPR_ASSERT(security_policy != nullptr);
108 
109   // Generate an unique connection ID that identifies this connection (Useful
110   // for mapping connection between Java and C++ code).
111   std::string connection_id =
112       grpc_binder::GetConnectionIdGenerator()->Generate(uri);
113 
114   gpr_log(GPR_ERROR, "connection id is %s", connection_id.c_str());
115 
116   // After invoking this Java method, Java code will put endpoint binder into
117   // `EndpointBinderPool` after the connection succeeds
118   // TODO(mingcl): Consider if we want to delay the connection establishment
119   // until SubchannelConnector start establishing connection. For now we don't
120   // see any benifits doing that.
121   grpc_binder::TryEstablishConnectionWithUri(static_cast<JNIEnv*>(jni_env_void),
122                                              context, uri, connection_id);
123 
124   grpc_channel_args channel_args;
125   args.SetChannelArgs(&channel_args);
126 
127   // Set server URI to a URI that contains connection id. The URI will be used
128   // by subchannel connector to obtain correct endpoint binder from
129   // `EndpointBinderPool`.
130   grpc_channel_args* new_args;
131   {
132     string server_uri = "binder:" + connection_id;
133     grpc_arg server_uri_arg =
134         grpc_channel_arg_string_create(const_cast<char*>(GRPC_ARG_SERVER_URI),
135                                        const_cast<char*>(server_uri.c_str()));
136     const char* to_remove[] = {GRPC_ARG_SERVER_URI};
137     new_args = grpc_channel_args_copy_and_add_and_remove(
138         &channel_args, to_remove, 1, &server_uri_arg, 1);
139   }
140 
141   grpc_binder::GetSecurityPolicySetting()->Set(connection_id, security_policy);
142 
143   auto channel = CreateChannelInternal(
144       "", grpc::internal::CreateClientBinderChannelImpl(new_args),
145       std::vector<
146           std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
147 
148   grpc_channel_args_destroy(new_args);
149 
150   return channel;
151 }
152 
InitializeBinderChannelJavaClass(void * jni_env_void)153 bool InitializeBinderChannelJavaClass(void* jni_env_void) {
154   return grpc_binder::FindNativeConnectionHelper(
155              static_cast<JNIEnv*>(jni_env_void)) != nullptr;
156 }
157 
InitializeBinderChannelJavaClass(void * jni_env_void,std::function<void * (std::string)> class_finder)158 bool InitializeBinderChannelJavaClass(
159     void* jni_env_void, std::function<void*(std::string)> class_finder) {
160   return grpc_binder::FindNativeConnectionHelper(
161              static_cast<JNIEnv*>(jni_env_void), class_finder) != nullptr;
162 }
163 
164 }  // namespace experimental
165 }  // namespace grpc
166 
167 #else  // !GPR_SUPPORT_BINDER_TRANSPORT
168 
169 namespace grpc {
170 namespace experimental {
171 
CreateBinderChannel(void *,jobject,absl::string_view,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>)172 std::shared_ptr<grpc::Channel> CreateBinderChannel(
173     void*, jobject, absl::string_view, absl::string_view,
174     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>) {
175   gpr_log(GPR_ERROR,
176           "This APK is compiled with Android API level = %d, which is not "
177           "supported. See port_platform.h for supported versions.",
178           __ANDROID_API__);
179   GPR_ASSERT(0);
180   return {};
181 }
182 
CreateCustomBinderChannel(void *,jobject,absl::string_view,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,const ChannelArguments &)183 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
184     void*, jobject, absl::string_view, absl::string_view,
185     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,
186     const ChannelArguments&) {
187   gpr_log(GPR_ERROR,
188           "This APK is compiled with Android API level = %d, which is not "
189           "supported. See port_platform.h for supported versions.",
190           __ANDROID_API__);
191   GPR_ASSERT(0);
192   return {};
193 }
194 
CreateBinderChannel(void *,jobject,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>)195 std::shared_ptr<grpc::Channel> CreateBinderChannel(
196     void*, jobject, absl::string_view,
197     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>) {
198   gpr_log(GPR_ERROR,
199           "This APK is compiled with Android API level = %d, which is not "
200           "supported. See port_platform.h for supported versions.",
201           __ANDROID_API__);
202   GPR_ASSERT(0);
203   return {};
204 }
205 
CreateCustomBinderChannel(void *,jobject,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,const ChannelArguments &)206 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
207     void*, jobject, absl::string_view,
208     std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,
209     const ChannelArguments&) {
210   gpr_log(GPR_ERROR,
211           "This APK is compiled with Android API level = %d, which is not "
212           "supported. See port_platform.h for supported versions.",
213           __ANDROID_API__);
214   GPR_ASSERT(0);
215   return {};
216 }
217 
InitializeBinderChannelJavaClass(void * jni_env_void)218 bool InitializeBinderChannelJavaClass(void* jni_env_void) {
219   gpr_log(GPR_ERROR,
220           "This APK is compiled with Android API level = %d, which is not "
221           "supported. See port_platform.h for supported versions.",
222           __ANDROID_API__);
223   GPR_ASSERT(0);
224   return {};
225 }
226 
InitializeBinderChannelJavaClass(void * jni_env_void,std::function<void * (std::string)> class_finder)227 bool InitializeBinderChannelJavaClass(
228     void* jni_env_void, std::function<void*(std::string)> class_finder) {
229   gpr_log(GPR_ERROR,
230           "This APK is compiled with Android API level = %d, which is not "
231           "supported. See port_platform.h for supported versions.",
232           __ANDROID_API__);
233   GPR_ASSERT(0);
234   return {};
235 }
236 
237 }  // namespace experimental
238 }  // namespace grpc
239 
240 #endif  // GPR_SUPPORT_BINDER_TRANSPORT
241 
242 #endif  // GPR_ANDROID
243 
244 #endif  // GRPC_NO_BINDER
245