1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <android-base/stringprintf.h>
17 #include <base/logging.h>
18 #include <nativehelper/ScopedPrimitiveArray.h>
19 #include <nativehelper/ScopedUtfChars.h>
20 
21 #include "JavaClassConstants.h"
22 #include "PeerToPeer.h"
23 
24 using android::base::StringPrintf;
25 
26 extern bool nfc_debug_enabled;
27 
28 namespace android {
29 
30 /*******************************************************************************
31 **
32 ** Function:        nativeLlcpSocket_doConnect
33 **
34 ** Description:     Establish a connection to the peer.
35 **                  e: JVM environment.
36 **                  o: Java object.
37 **                  nSap: Service access point.
38 **
39 ** Returns:         True if ok.
40 **
41 *******************************************************************************/
nativeLlcpSocket_doConnect(JNIEnv * e,jobject o,jint nSap)42 static jboolean nativeLlcpSocket_doConnect(JNIEnv* e, jobject o, jint nSap) {
43   DLOG_IF(INFO, nfc_debug_enabled)
44       << StringPrintf("%s: enter; sap=%d", __func__, nSap);
45 
46   PeerToPeer::tJNI_HANDLE jniHandle =
47       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
48   bool stat = PeerToPeer::getInstance().connectConnOriented(jniHandle, nSap);
49 
50   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
51   return stat ? JNI_TRUE : JNI_FALSE;
52 }
53 
54 /*******************************************************************************
55 **
56 ** Function:        nativeLlcpSocket_doConnectBy
57 **
58 ** Description:     Establish a connection to the peer.
59 **                  e: JVM environment.
60 **                  o: Java object.
61 **                  sn: Service name.
62 **
63 ** Returns:         True if ok.
64 **
65 *******************************************************************************/
nativeLlcpSocket_doConnectBy(JNIEnv * e,jobject o,jstring sn)66 static jboolean nativeLlcpSocket_doConnectBy(JNIEnv* e, jobject o, jstring sn) {
67   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
68 
69   PeerToPeer::tJNI_HANDLE jniHandle =
70       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
71 
72   ScopedUtfChars serviceName(e, sn);
73   if (serviceName.c_str() == NULL) {
74     return JNI_FALSE;
75   }
76   bool stat = PeerToPeer::getInstance().connectConnOriented(
77       jniHandle, serviceName.c_str());
78 
79   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
80   return stat ? JNI_TRUE : JNI_FALSE;
81 }
82 
83 /*******************************************************************************
84 **
85 ** Function:        nativeLlcpSocket_doClose
86 **
87 ** Description:     Close socket.
88 **                  e: JVM environment.
89 **                  o: Java object.
90 **
91 ** Returns:         True if ok.
92 **
93 *******************************************************************************/
nativeLlcpSocket_doClose(JNIEnv * e,jobject o)94 static jboolean nativeLlcpSocket_doClose(JNIEnv* e, jobject o) {
95   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
96 
97   PeerToPeer::tJNI_HANDLE jniHandle =
98       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
99   bool stat = PeerToPeer::getInstance().disconnectConnOriented(jniHandle);
100 
101   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
102   return stat ? JNI_TRUE : JNI_FALSE;
103 }
104 
105 /*******************************************************************************
106 **
107 ** Function:        nativeLlcpSocket_doSend
108 **
109 ** Description:     Send data to peer.
110 **                  e: JVM environment.
111 **                  o: Java object.
112 **                  data: Buffer of data.
113 **
114 ** Returns:         True if sent ok.
115 **
116 *******************************************************************************/
nativeLlcpSocket_doSend(JNIEnv * e,jobject o,jbyteArray data)117 static jboolean nativeLlcpSocket_doSend(JNIEnv* e, jobject o, jbyteArray data) {
118   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
119 
120   ScopedByteArrayRO bytes(e, data);
121 
122   PeerToPeer::tJNI_HANDLE jniHandle =
123       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
124   uint8_t* raw_ptr = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(
125       &bytes[0]));  // TODO: API bug: send should take const*!
126   bool stat = PeerToPeer::getInstance().send(jniHandle, raw_ptr, bytes.size());
127 
128   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
129   return stat ? JNI_TRUE : JNI_FALSE;
130 }
131 
132 /*******************************************************************************
133 **
134 ** Function:        nativeLlcpSocket_doReceive
135 **
136 ** Description:     Receive data from peer.
137 **                  e: JVM environment.
138 **                  o: Java object.
139 **                  origBuffer: Buffer to put received data.
140 **
141 ** Returns:         Number of bytes received.
142 **
143 *******************************************************************************/
nativeLlcpSocket_doReceive(JNIEnv * e,jobject o,jbyteArray origBuffer)144 static jint nativeLlcpSocket_doReceive(JNIEnv* e, jobject o,
145                                        jbyteArray origBuffer) {
146   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
147 
148   ScopedByteArrayRW bytes(e, origBuffer);
149 
150   PeerToPeer::tJNI_HANDLE jniHandle =
151       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
152   uint16_t actualLen = 0;
153   bool stat = PeerToPeer::getInstance().receive(
154       jniHandle, reinterpret_cast<uint8_t*>(&bytes[0]), bytes.size(),
155       actualLen);
156 
157   jint retval = 0;
158   if (stat && (actualLen > 0)) {
159     retval = actualLen;
160   } else
161     retval = -1;
162 
163   DLOG_IF(INFO, nfc_debug_enabled)
164       << StringPrintf("%s: exit; actual len=%d", __func__, retval);
165   return retval;
166 }
167 
168 /*******************************************************************************
169 **
170 ** Function:        nativeLlcpSocket_doGetRemoteSocketMIU
171 **
172 ** Description:     Get peer's maximum information unit.
173 **                  e: JVM environment.
174 **                  o: Java object.
175 **
176 ** Returns:         Peer's maximum information unit.
177 **
178 *******************************************************************************/
nativeLlcpSocket_doGetRemoteSocketMIU(JNIEnv * e,jobject o)179 static jint nativeLlcpSocket_doGetRemoteSocketMIU(JNIEnv* e, jobject o) {
180   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
181 
182   PeerToPeer::tJNI_HANDLE jniHandle =
183       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
184   jint miu = PeerToPeer::getInstance().getRemoteMaxInfoUnit(jniHandle);
185 
186   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
187   return miu;
188 }
189 
190 /*******************************************************************************
191 **
192 ** Function:        nativeLlcpSocket_doGetRemoteSocketRW
193 **
194 ** Description:     Get peer's receive window size.
195 **                  e: JVM environment.
196 **                  o: Java object.
197 **
198 ** Returns:         Peer's receive window size.
199 **
200 *******************************************************************************/
nativeLlcpSocket_doGetRemoteSocketRW(JNIEnv * e,jobject o)201 static jint nativeLlcpSocket_doGetRemoteSocketRW(JNIEnv* e, jobject o) {
202   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
203 
204   PeerToPeer::tJNI_HANDLE jniHandle =
205       (PeerToPeer::tJNI_HANDLE)nfc_jni_get_nfc_socket_handle(e, o);
206   jint rw = PeerToPeer::getInstance().getRemoteRecvWindow(jniHandle);
207 
208   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
209   return rw;
210 }
211 
212 /*****************************************************************************
213 **
214 ** Description:     JNI functions
215 **
216 *****************************************************************************/
217 static JNINativeMethod gMethods[] = {
218     {"doConnect", "(I)Z", (void*)nativeLlcpSocket_doConnect},
219     {"doConnectBy", "(Ljava/lang/String;)Z",
220      (void*)nativeLlcpSocket_doConnectBy},
221     {"doClose", "()Z", (void*)nativeLlcpSocket_doClose},
222     {"doSend", "([B)Z", (void*)nativeLlcpSocket_doSend},
223     {"doReceive", "([B)I", (void*)nativeLlcpSocket_doReceive},
224     {"doGetRemoteSocketMiu", "()I",
225      (void*)nativeLlcpSocket_doGetRemoteSocketMIU},
226     {"doGetRemoteSocketRw", "()I", (void*)nativeLlcpSocket_doGetRemoteSocketRW},
227 };
228 
229 /*******************************************************************************
230 **
231 ** Function:        register_com_android_nfc_NativeLlcpSocket
232 **
233 ** Description:     Regisgter JNI functions with Java Virtual Machine.
234 **                  e: Environment of JVM.
235 **
236 ** Returns:         Status of registration.
237 **
238 *******************************************************************************/
register_com_android_nfc_NativeLlcpSocket(JNIEnv * e)239 int register_com_android_nfc_NativeLlcpSocket(JNIEnv* e) {
240   return jniRegisterNativeMethods(e, gNativeLlcpSocketClassName, gMethods,
241                                   NELEM(gMethods));
242 }
243 
244 }  // namespace android
245