Merge "Add error codes for channel disconnection / connection."
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index c165d92..9b2b8ca 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -81,6 +81,20 @@
*/
public static final int CHANNEL_TYPE_ANY = 12;
+ /** @hide */
+ public static final int HEALTH_OPERATION_SUCCESS = 6000;
+ /** @hide */
+ public static final int HEALTH_OPERATION_ERROR = 6001;
+ /** @hide */
+ public static final int HEALTH_OPERATION_INVALID_ARGS = 6002;
+ /** @hide */
+ public static final int HEALTH_OPERATION_GENERIC_FAILURE = 6003;
+ /** @hide */
+ public static final int HEALTH_OPERATION_NOT_FOUND = 6004;
+ /** @hide */
+ public static final int HEALTH_OPERATION_NOT_ALLOWED = 6005;
+
+
/**
* Register an application configuration that acts as a Health SINK.
* This is the configuration that will be used to communicate with health devices
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index e4f2d32..56da69d 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -20,6 +20,7 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealth;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -974,6 +975,22 @@
}
/**
+ * Called by native code for the async response to a Connect
+ * method call to org.bluez.Health
+ *
+ * @param chanCode The internal id of the channel
+ * @param result Result code of the operation.
+ */
+ private void onHealthDeviceConnectionResult(int chanCode, int result) {
+ log ("onHealthDeviceConnectionResult " + chanCode + " " + result);
+ // Success case gets handled by Property Change signal
+ if (result != BluetoothHealth.HEALTH_OPERATION_SUCCESS) {
+ mBluetoothService.onHealthDeviceChannelConnectionError(chanCode,
+ BluetoothHealth.STATE_CHANNEL_DISCONNECTED);
+ }
+ }
+
+ /**
* Called by native code on a DeviceDisconnected signal from
* org.bluez.NetworkServer.
*
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
index a6ada2b..2d80de4 100644
--- a/core/java/android/server/BluetoothHealthProfileHandler.java
+++ b/core/java/android/server/BluetoothHealthProfileHandler.java
@@ -84,7 +84,6 @@
result = 31 * result + (mChannelPath == null ? 0 : mChannelPath.hashCode());
result = 31 * result + mDevice.hashCode();
result = 31 * result + mConfig.hashCode();
- result = 31 * result + mState;
result = 31 * result + mChannelType;
return result;
}
@@ -152,7 +151,7 @@
String channelType = getStringChannelType(chan.mChannelType);
if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath,
- channelType)) {
+ channelType, chan.hashCode())) {
int prevState = chan.mState;
int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
@@ -258,7 +257,7 @@
boolean disconnectChannel(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int id) {
- HealthChannel chan = findChannelById(device, config, id);
+ HealthChannel chan = findChannelById(id);
if (chan == null) {
return false;
}
@@ -273,7 +272,8 @@
callHealthChannelCallback(config, device, prevState, chan.mState,
null, chan.hashCode());
- if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
+ if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath,
+ chan.hashCode())) {
prevState = chan.mState;
chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
callHealthChannelCallback(config, device, prevState, chan.mState,
@@ -284,8 +284,7 @@
}
}
- private HealthChannel findChannelById(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, int id) {
+ private HealthChannel findChannelById(int id) {
for (HealthChannel chan : mHealthChannels) {
if (chan.hashCode() == id) return chan;
}
@@ -384,6 +383,15 @@
}
}
+ /*package*/ void onHealthDeviceChannelConnectionError(int chanCode,
+ int state) {
+ HealthChannel channel = findChannelById(chanCode);
+ if (channel == null) errorLog("No record of this channel:" + chanCode);
+
+ callHealthChannelCallback(channel.mConfig, channel.mDevice, channel.mState, state, null,
+ chanCode);
+ }
+
private BluetoothHealthAppConfiguration findHealthApplication(
BluetoothDevice device, String channelPath) {
BluetoothHealthAppConfiguration config = null;
@@ -424,9 +432,19 @@
config = findHealthApplication(device, channelPath);
if (exists) {
+ channel = findConnectingChannel(device, config);
+ if (channel == null) {
+ channel = new HealthChannel(device, config, null, false,
+ channelPath);
+ channel.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ mHealthChannels.add(channel);
+ }
+ channel.mChannelPath = channelPath;
+
fd = mBluetoothService.getChannelFdNative(channelPath);
if (fd == null) {
errorLog("Error obtaining fd for channel:" + channelPath);
+ disconnectChannel(device, config, channel.hashCode());
return;
}
boolean mainChannel =
@@ -440,18 +458,10 @@
}
if (mainChannelPath.equals(channelPath)) mainChannel = true;
}
- channel = findConnectingChannel(device, config);
- if (channel != null) {
- channel.mChannelFd = fd;
- channel.mMainChannel = mainChannel;
- channel.mChannelPath = channelPath;
- prevState = channel.mState;
- } else {
- channel = new HealthChannel(device, config, fd, mainChannel,
- channelPath);
- mHealthChannels.add(channel);
- prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
- }
+
+ channel.mChannelFd = fd;
+ channel.mMainChannel = mainChannel;
+ prevState = channel.mState;
state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
} else {
channel = findChannelByPath(device, channelPath);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 03180ca..00d3331 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2255,6 +2255,14 @@
}
}
+ /*package*/ void onHealthDeviceChannelConnectionError(int channelCode,
+ int newState) {
+ synchronized(mBluetoothHealthProfileHandler) {
+ mBluetoothHealthProfileHandler.onHealthDeviceChannelConnectionError(channelCode,
+ newState);
+ }
+ }
+
public int getHealthDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission");
@@ -2785,8 +2793,9 @@
String channelType);
native String registerHealthApplicationNative(int dataType, String role, String name);
native boolean unregisterHealthApplicationNative(String path);
- native boolean createChannelNative(String devicePath, String appPath, String channelType);
- native boolean destroyChannelNative(String devicePath, String channelpath);
+ native boolean createChannelNative(String devicePath, String appPath, String channelType,
+ int code);
+ native boolean destroyChannelNative(String devicePath, String channelpath, int code);
native String getMainChannelNative(String path);
native String getChannelApplicationNative(String channelPath);
native ParcelFileDescriptor getChannelFdNative(String channelPath);
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
index 2f5fd5a..1f4da3a 100644
--- a/core/jni/android_bluetooth_common.h
+++ b/core/jni/android_bluetooth_common.h
@@ -202,6 +202,13 @@
#define INPUT_OPERATION_GENERIC_FAILURE 5003
#define INPUT_OPERATION_SUCCESS 5004
+#define HEALTH_OPERATION_SUCCESS 6000
+#define HEALTH_OPERATION_ERROR 6001
+#define HEALTH_OPERATION_INVALID_ARGS 6002
+#define HEALTH_OPERATION_GENERIC_FAILURE 6003
+#define HEALTH_OPERATION_NOT_FOUND 6004
+#define HEALTH_OPERATION_NOT_ALLOWED 6005
+
#endif
} /* namespace android */
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index eee256a..0335ce7 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -74,6 +74,7 @@
static jmethodID method_onPanDeviceConnectionResult;
static jmethodID method_onHealthDevicePropertyChanged;
static jmethodID method_onHealthDeviceChannelChanged;
+static jmethodID method_onHealthDeviceConnectionResult;
typedef event_loop_native_data_t native_data_t;
@@ -141,6 +142,9 @@
"(Ljava/lang/String;[Ljava/lang/String;)V");
method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
"(Ljava/lang/String;I)V");
+ method_onHealthDeviceConnectionResult = env->GetMethodID(clazz,
+ "onHealthDeviceConnectionResult",
+ "(II)V");
method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
"(Ljava/lang/String;[Ljava/lang/String;)V");
method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
@@ -1533,6 +1537,39 @@
free(user);
}
+void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
+ LOGV("%s", __FUNCTION__);
+
+ native_data_t *nat = (native_data_t *)n;
+ DBusError err;
+ dbus_error_init(&err);
+ JNIEnv *env;
+ nat->vm->GetEnv((void**)&env, nat->envVer);
+
+ jint result = HEALTH_OPERATION_SUCCESS;
+ if (dbus_set_error_from_message(&err, msg)) {
+ if (!strcmp(err.name, BLUEZ_ERROR_IFC ".InvalidArgs")) {
+ result = HEALTH_OPERATION_INVALID_ARGS;
+ } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".HealthError")) {
+ result = HEALTH_OPERATION_ERROR;
+ } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotFound")) {
+ result = HEALTH_OPERATION_NOT_FOUND;
+ } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotAllowed")) {
+ result = HEALTH_OPERATION_NOT_ALLOWED;
+ } else {
+ result = HEALTH_OPERATION_GENERIC_FAILURE;
+ }
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+
+ LOGV("... Health Device Code = %d, result = %d", code, result);
+ jint code = *(int *) user;
+ env->CallVoidMethod(nat->me,
+ method_onHealthDeviceConnectionResult,
+ code,
+ result);
+ free(user);
+}
#endif
static JNINativeMethod sMethods[] = {
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 292047b..a49c918 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -78,8 +78,8 @@
void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat);
void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat);
void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-void onConnectPanResult(DBusMessage *msg, void *user, void *n);
void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
+void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
/** Get native data stored in the opaque (Java code maintained) pointer mNativeData
@@ -1450,79 +1450,70 @@
}
static jboolean createChannelNative(JNIEnv *env, jobject object,
- jstring devicePath, jstring appPath, jstring config) {
+ jstring devicePath, jstring appPath, jstring config,
+ jint code) {
LOGV("%s", __FUNCTION__);
- jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object);
+ jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
+ struct event_loop_native_data_t *eventLoopNat =
+ get_EventLoop_native_data(env, eventLoop);
- if (nat) {
- DBusError err;
- dbus_error_init(&err);
-
+ if (nat && eventLoopNat) {
const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
const char *c_config = env->GetStringUTFChars(config, NULL);
+ int *data = (int *) malloc(sizeof(int));
+ if (data == NULL) return JNI_FALSE;
- DBusMessage *reply = dbus_func_args(env, nat->conn,
- c_device_path,
- DBUS_HEALTH_DEVICE_IFACE,
- "CreateChannel",
- DBUS_TYPE_OBJECT_PATH, &c_app_path,
- DBUS_TYPE_STRING, &c_config,
- DBUS_TYPE_INVALID);
+ *data = code;
+ bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
+ data, eventLoopNat, c_device_path,
+ DBUS_HEALTH_DEVICE_IFACE, "CreateChannel",
+ DBUS_TYPE_OBJECT_PATH, &c_app_path,
+ DBUS_TYPE_STRING, &c_config,
+ DBUS_TYPE_INVALID);
env->ReleaseStringUTFChars(devicePath, c_device_path);
env->ReleaseStringUTFChars(appPath, c_app_path);
env->ReleaseStringUTFChars(config, c_config);
- if (!reply) {
- if (dbus_error_is_set(&err)) {
- LOG_AND_FREE_DBUS_ERROR(&err);
- }
- } else {
- result = JNI_TRUE;
- }
+ return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
- return result;
+ return JNI_FALSE;
}
static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
- jstring channelPath) {
+ jstring channelPath, jint code) {
LOGE("%s", __FUNCTION__);
- jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object);
+ jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
+ struct event_loop_native_data_t *eventLoopNat =
+ get_EventLoop_native_data(env, eventLoop);
- if (nat) {
- DBusError err;
- dbus_error_init(&err);
-
+ if (nat && eventLoopNat) {
const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+ int *data = (int *) malloc(sizeof(int));
+ if (data == NULL) return JNI_FALSE;
- DBusMessage *reply = dbus_func_args(env, nat->conn,
- c_device_path,
- DBUS_HEALTH_DEVICE_IFACE,
- "DestroyChannel",
- DBUS_TYPE_OBJECT_PATH, &c_channel_path,
- DBUS_TYPE_INVALID);
+ *data = code;
+ bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
+ data, eventLoopNat, c_device_path,
+ DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel",
+ DBUS_TYPE_OBJECT_PATH, &c_channel_path,
+ DBUS_TYPE_INVALID);
env->ReleaseStringUTFChars(devicePath, c_device_path);
env->ReleaseStringUTFChars(channelPath, c_channel_path);
- if (!reply) {
- if (dbus_error_is_set(&err)) {
- LOG_AND_FREE_DBUS_ERROR(&err);
- }
- } else {
- result = JNI_TRUE;
- }
+ return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
- return result;
+ return JNI_FALSE;
}
static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
@@ -1755,9 +1746,10 @@
{"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z",
(void *)unregisterHealthApplicationNative},
- {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+ {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z",
(void *)createChannelNative},
- {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)destroyChannelNative},
+ {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
+ (void *)destroyChannelNative},
{"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative},
{"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;",
(void *)getChannelApplicationNative},