Merge "Add error codes for channel disconnection / connection."

This commit is contained in:
Jaikumar Ganesh
2011-09-09 15:19:43 -07:00
committed by Android (Google) Code Review
7 changed files with 150 additions and 64 deletions

View File

@@ -81,6 +81,20 @@ public final class BluetoothHealth implements BluetoothProfile {
*/ */
public static final int CHANNEL_TYPE_ANY = 12; 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. * Register an application configuration that acts as a Health SINK.
* This is the configuration that will be used to communicate with health devices * This is the configuration that will be used to communicate with health devices

View File

@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealth;
import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
@@ -973,6 +974,22 @@ class BluetoothEventLoop {
} }
} }
/**
* 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 * Called by native code on a DeviceDisconnected signal from
* org.bluez.NetworkServer. * org.bluez.NetworkServer.

View File

@@ -84,7 +84,6 @@ final class BluetoothHealthProfileHandler {
result = 31 * result + (mChannelPath == null ? 0 : mChannelPath.hashCode()); result = 31 * result + (mChannelPath == null ? 0 : mChannelPath.hashCode());
result = 31 * result + mDevice.hashCode(); result = 31 * result + mDevice.hashCode();
result = 31 * result + mConfig.hashCode(); result = 31 * result + mConfig.hashCode();
result = 31 * result + mState;
result = 31 * result + mChannelType; result = 31 * result + mChannelType;
return result; return result;
} }
@@ -152,7 +151,7 @@ final class BluetoothHealthProfileHandler {
String channelType = getStringChannelType(chan.mChannelType); String channelType = getStringChannelType(chan.mChannelType);
if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath, if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath,
channelType)) { channelType, chan.hashCode())) {
int prevState = chan.mState; int prevState = chan.mState;
int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED; int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null, callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
@@ -258,7 +257,7 @@ final class BluetoothHealthProfileHandler {
boolean disconnectChannel(BluetoothDevice device, boolean disconnectChannel(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int id) { BluetoothHealthAppConfiguration config, int id) {
HealthChannel chan = findChannelById(device, config, id); HealthChannel chan = findChannelById(id);
if (chan == null) { if (chan == null) {
return false; return false;
} }
@@ -273,7 +272,8 @@ final class BluetoothHealthProfileHandler {
callHealthChannelCallback(config, device, prevState, chan.mState, callHealthChannelCallback(config, device, prevState, chan.mState,
null, chan.hashCode()); null, chan.hashCode());
if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) { if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath,
chan.hashCode())) {
prevState = chan.mState; prevState = chan.mState;
chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED; chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
callHealthChannelCallback(config, device, prevState, chan.mState, callHealthChannelCallback(config, device, prevState, chan.mState,
@@ -284,8 +284,7 @@ final class BluetoothHealthProfileHandler {
} }
} }
private HealthChannel findChannelById(BluetoothDevice device, private HealthChannel findChannelById(int id) {
BluetoothHealthAppConfiguration config, int id) {
for (HealthChannel chan : mHealthChannels) { for (HealthChannel chan : mHealthChannels) {
if (chan.hashCode() == id) return chan; if (chan.hashCode() == id) return chan;
} }
@@ -384,6 +383,15 @@ final class BluetoothHealthProfileHandler {
} }
} }
/*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( private BluetoothHealthAppConfiguration findHealthApplication(
BluetoothDevice device, String channelPath) { BluetoothDevice device, String channelPath) {
BluetoothHealthAppConfiguration config = null; BluetoothHealthAppConfiguration config = null;
@@ -424,9 +432,19 @@ final class BluetoothHealthProfileHandler {
config = findHealthApplication(device, channelPath); config = findHealthApplication(device, channelPath);
if (exists) { 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); fd = mBluetoothService.getChannelFdNative(channelPath);
if (fd == null) { if (fd == null) {
errorLog("Error obtaining fd for channel:" + channelPath); errorLog("Error obtaining fd for channel:" + channelPath);
disconnectChannel(device, config, channel.hashCode());
return; return;
} }
boolean mainChannel = boolean mainChannel =
@@ -440,18 +458,10 @@ final class BluetoothHealthProfileHandler {
} }
if (mainChannelPath.equals(channelPath)) mainChannel = true; if (mainChannelPath.equals(channelPath)) mainChannel = true;
} }
channel = findConnectingChannel(device, config);
if (channel != null) { channel.mChannelFd = fd;
channel.mChannelFd = fd; channel.mMainChannel = mainChannel;
channel.mMainChannel = mainChannel; prevState = channel.mState;
channel.mChannelPath = channelPath;
prevState = channel.mState;
} else {
channel = new HealthChannel(device, config, fd, mainChannel,
channelPath);
mHealthChannels.add(channel);
prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
}
state = BluetoothHealth.STATE_CHANNEL_CONNECTED; state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
} else { } else {
channel = findChannelByPath(device, channelPath); channel = findChannelByPath(device, channelPath);

View File

@@ -2255,6 +2255,14 @@ public class BluetoothService extends IBluetooth.Stub {
} }
} }
/*package*/ void onHealthDeviceChannelConnectionError(int channelCode,
int newState) {
synchronized(mBluetoothHealthProfileHandler) {
mBluetoothHealthProfileHandler.onHealthDeviceChannelConnectionError(channelCode,
newState);
}
}
public int getHealthDeviceConnectionState(BluetoothDevice device) { public int getHealthDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission"); "Need BLUETOOTH permission");
@@ -2785,8 +2793,9 @@ public class BluetoothService extends IBluetooth.Stub {
String channelType); String channelType);
native String registerHealthApplicationNative(int dataType, String role, String name); native String registerHealthApplicationNative(int dataType, String role, String name);
native boolean unregisterHealthApplicationNative(String path); native boolean unregisterHealthApplicationNative(String path);
native boolean createChannelNative(String devicePath, String appPath, String channelType); native boolean createChannelNative(String devicePath, String appPath, String channelType,
native boolean destroyChannelNative(String devicePath, String channelpath); int code);
native boolean destroyChannelNative(String devicePath, String channelpath, int code);
native String getMainChannelNative(String path); native String getMainChannelNative(String path);
native String getChannelApplicationNative(String channelPath); native String getChannelApplicationNative(String channelPath);
native ParcelFileDescriptor getChannelFdNative(String channelPath); native ParcelFileDescriptor getChannelFdNative(String channelPath);

View File

@@ -202,6 +202,13 @@ bool debug_no_encrypt();
#define INPUT_OPERATION_GENERIC_FAILURE 5003 #define INPUT_OPERATION_GENERIC_FAILURE 5003
#define INPUT_OPERATION_SUCCESS 5004 #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 #endif
} /* namespace android */ } /* namespace android */

View File

@@ -74,6 +74,7 @@ static jmethodID method_onPanDevicePropertyChanged;
static jmethodID method_onPanDeviceConnectionResult; static jmethodID method_onPanDeviceConnectionResult;
static jmethodID method_onHealthDevicePropertyChanged; static jmethodID method_onHealthDevicePropertyChanged;
static jmethodID method_onHealthDeviceChannelChanged; static jmethodID method_onHealthDeviceChannelChanged;
static jmethodID method_onHealthDeviceConnectionResult;
typedef event_loop_native_data_t native_data_t; typedef event_loop_native_data_t native_data_t;
@@ -141,6 +142,9 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
"(Ljava/lang/String;[Ljava/lang/String;)V"); "(Ljava/lang/String;[Ljava/lang/String;)V");
method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult", method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
"(Ljava/lang/String;I)V"); "(Ljava/lang/String;I)V");
method_onHealthDeviceConnectionResult = env->GetMethodID(clazz,
"onHealthDeviceConnectionResult",
"(II)V");
method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged", method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
"(Ljava/lang/String;[Ljava/lang/String;)V"); "(Ljava/lang/String;[Ljava/lang/String;)V");
method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged", method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
@@ -1533,6 +1537,39 @@ void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
free(user); 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 #endif
static JNINativeMethod sMethods[] = { static JNINativeMethod sMethods[] = {

View File

@@ -78,8 +78,8 @@ void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat);
void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat); void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat);
void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat); void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat);
void onInputDeviceConnectionResult(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 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 /** Get native data stored in the opaque (Java code maintained) pointer mNativeData
@@ -1450,79 +1450,70 @@ static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object,
} }
static jboolean createChannelNative(JNIEnv *env, jobject object, static jboolean createChannelNative(JNIEnv *env, jobject object,
jstring devicePath, jstring appPath, jstring config) { jstring devicePath, jstring appPath, jstring config,
jint code) {
LOGV("%s", __FUNCTION__); LOGV("%s", __FUNCTION__);
jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH #ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object); 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) { if (nat && eventLoopNat) {
DBusError err;
dbus_error_init(&err);
const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
const char *c_app_path = env->GetStringUTFChars(appPath, NULL); const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
const char *c_config = env->GetStringUTFChars(config, 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, *data = code;
c_device_path, bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
DBUS_HEALTH_DEVICE_IFACE, data, eventLoopNat, c_device_path,
"CreateChannel", DBUS_HEALTH_DEVICE_IFACE, "CreateChannel",
DBUS_TYPE_OBJECT_PATH, &c_app_path, DBUS_TYPE_OBJECT_PATH, &c_app_path,
DBUS_TYPE_STRING, &c_config, DBUS_TYPE_STRING, &c_config,
DBUS_TYPE_INVALID); DBUS_TYPE_INVALID);
env->ReleaseStringUTFChars(devicePath, c_device_path); env->ReleaseStringUTFChars(devicePath, c_device_path);
env->ReleaseStringUTFChars(appPath, c_app_path); env->ReleaseStringUTFChars(appPath, c_app_path);
env->ReleaseStringUTFChars(config, c_config); env->ReleaseStringUTFChars(config, c_config);
if (!reply) { return ret ? JNI_TRUE : JNI_FALSE;
if (dbus_error_is_set(&err)) {
LOG_AND_FREE_DBUS_ERROR(&err);
}
} else {
result = JNI_TRUE;
}
} }
#endif #endif
return result; return JNI_FALSE;
} }
static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath, static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
jstring channelPath) { jstring channelPath, jint code) {
LOGE("%s", __FUNCTION__); LOGE("%s", __FUNCTION__);
jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH #ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object); 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) { if (nat && eventLoopNat) {
DBusError err;
dbus_error_init(&err);
const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
const char *c_channel_path = env->GetStringUTFChars(channelPath, 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, *data = code;
c_device_path, bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
DBUS_HEALTH_DEVICE_IFACE, data, eventLoopNat, c_device_path,
"DestroyChannel", DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel",
DBUS_TYPE_OBJECT_PATH, &c_channel_path, DBUS_TYPE_OBJECT_PATH, &c_channel_path,
DBUS_TYPE_INVALID); DBUS_TYPE_INVALID);
env->ReleaseStringUTFChars(devicePath, c_device_path); env->ReleaseStringUTFChars(devicePath, c_device_path);
env->ReleaseStringUTFChars(channelPath, c_channel_path); env->ReleaseStringUTFChars(channelPath, c_channel_path);
if (!reply) { return ret ? JNI_TRUE : JNI_FALSE;
if (dbus_error_is_set(&err)) {
LOG_AND_FREE_DBUS_ERROR(&err);
}
} else {
result = JNI_TRUE;
}
} }
#endif #endif
return result; return JNI_FALSE;
} }
static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) { static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
@@ -1755,9 +1746,10 @@ static JNINativeMethod sMethods[] = {
{"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z", {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z",
(void *)unregisterHealthApplicationNative}, (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}, (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}, {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative},
{"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;", {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;",
(void *)getChannelApplicationNative}, (void *)getChannelApplicationNative},