diff options
Diffstat (limited to 'core/jni')
-rw-r--r-- | core/jni/android_bluetooth_BluetoothSocket.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp index 4c84324..488b5c2 100644 --- a/core/jni/android_bluetooth_BluetoothSocket.cpp +++ b/core/jni/android_bluetooth_BluetoothSocket.cpp @@ -57,6 +57,9 @@ static const int TYPE_L2CAP = 3; // TODO: Test l2cap code paths static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer +static void abortNative(JNIEnv *env, jobject obj); +static void destroyNative(JNIEnv *env, jobject obj); + static struct asocket *get_socketData(JNIEnv *env, jobject obj) { struct asocket *s = (struct asocket *) env->GetIntField(obj, field_mSocketData); @@ -172,6 +175,7 @@ static void connectNative(JNIEnv *env, jobject obj) { socklen_t addr_sz; struct sockaddr *addr; struct asocket *s = get_socketData(env, obj); + int retry = 0; if (!s) return; @@ -226,10 +230,30 @@ static void connectNative(JNIEnv *env, jobject obj) { return; } +connect: ret = asocket_connect(s, addr, addr_sz, -1); LOGV("...connect(%d, %s) = %d (errno %d)", s->fd, TYPE_AS_STR(type), ret, errno); + if (ret && errno == EALREADY && retry < 2) { + /* workaround for bug 5082381 (EALREADY on ACL collision): + * retry the connect. Unfortunately we have to create a new fd. + * It's not ideal to switch the fd underneath the object, but + * is currently safe */ + LOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround"); + usleep(100000); + retry++; + abortNative(env, obj); + destroyNative(env, obj); + initSocketNative(env, obj); + if (env->ExceptionOccurred()) { + return; + } + goto connect; + } + if (!ret && retry > 0) + LOGD("...workaround ok"); + if (ret) jniThrowIOException(env, errno); |