Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c057832e authored by Mike Playle's avatar Mike Playle Committed by Steve Kondik
Browse files

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
parent a877d142
Loading
Loading
Loading
Loading
+13 −7
Original line number Original line Diff line number Diff line
@@ -448,7 +448,7 @@ static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
#ifdef HAVE_BLUETOOTH
#ifdef HAVE_BLUETOOTH
    LOGV(__FUNCTION__);
    LOGV(__FUNCTION__);


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


    total = 0;
    while (length > 0) {
        ret = asocket_write(s, &b[offset], length, -1);
        ret = asocket_write(s, &b[offset], length, -1);
        if (ret < 0) {
        if (ret < 0) {
            jniThrowIOException(env, errno);
            jniThrowIOException(env, errno);
            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
            return -1;
            return -1;
        }
        }
        offset += ret;
        total += ret;
        length -= ret;
    }


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


#endif
#endif
    jniThrowIOException(env, ENOSYS);
    jniThrowIOException(env, ENOSYS);