Skip to content

Commit 36aa883

Browse files
author
Mike Playle
committed
Fix data corruption when writing to Bluetooth socket
Writes to Bluetooth sockets are handled by writeNative() in android_bluetooth_BluetoothSocket.cpp. This calls asocket_write() which is implemented in abort_socket.c. This latter function sleeps until poll() indicates that the socket is writeable, then calls write() once, returning the number of bytes written. However writeNative() just returns this byte count to the caller; it's eventually ignored in BluetoothOutputStream.java. This doesn't match the semantics of a Java OutputStream, which is required to block until all bytes have been written. This fix adds a loop to writeNative() that repeatedly calls the lower level write function until all the data has been written (or an error occurred in which case we should exit the loop early). With this change it is possible to write large amounts of data to a Bluetooth socket without experiencing data loss. Change-Id: I0b464382817e15adec32ba0e3cb37e7d1cccc730
1 parent c6b22e2 commit 36aa883

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

core/jni/android_bluetooth_BluetoothSocket.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
448448
#ifdef HAVE_BLUETOOTH
449449
LOGV(__FUNCTION__);
450450

451-
int ret;
451+
int ret, total;
452452
jbyte *b;
453453
int sz;
454454
struct asocket *s = get_socketData(env, obj);
@@ -471,15 +471,21 @@ static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
471471
return -1;
472472
}
473473

474-
ret = asocket_write(s, &b[offset], length, -1);
475-
if (ret < 0) {
476-
jniThrowIOException(env, errno);
477-
env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
478-
return -1;
474+
total = 0;
475+
while (length > 0) {
476+
ret = asocket_write(s, &b[offset], length, -1);
477+
if (ret < 0) {
478+
jniThrowIOException(env, errno);
479+
env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
480+
return -1;
481+
}
482+
offset += ret;
483+
total += ret;
484+
length -= ret;
479485
}
480486

481487
env->ReleaseByteArrayElements(jb, b, JNI_ABORT); // no need to commit
482-
return (jint)ret;
488+
return (jint)total;
483489

484490
#endif
485491
jniThrowIOException(env, ENOSYS);

0 commit comments

Comments
 (0)