Merge "Add error codes for channel disconnection / connection."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6d172e60bb
@@ -81,6 +81,20 @@ public final class BluetoothHealth implements BluetoothProfile {
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothA2dp;
|
||||
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;
|
||||
@@ -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
|
||||
* org.bluez.NetworkServer.
|
||||
|
||||
@@ -84,7 +84,6 @@ final class BluetoothHealthProfileHandler {
|
||||
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 @@ final class BluetoothHealthProfileHandler {
|
||||
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 @@ final class BluetoothHealthProfileHandler {
|
||||
|
||||
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 @@ final class BluetoothHealthProfileHandler {
|
||||
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 @@ final class BluetoothHealthProfileHandler {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ 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(
|
||||
BluetoothDevice device, String channelPath) {
|
||||
BluetoothHealthAppConfiguration config = null;
|
||||
@@ -424,9 +432,19 @@ final class BluetoothHealthProfileHandler {
|
||||
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 @@ final class BluetoothHealthProfileHandler {
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -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) {
|
||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
|
||||
"Need BLUETOOTH permission");
|
||||
@@ -2785,8 +2793,9 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
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);
|
||||
|
||||
@@ -202,6 +202,13 @@ bool debug_no_encrypt();
|
||||
#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 */
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ static jmethodID method_onPanDevicePropertyChanged;
|
||||
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 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
|
||||
"(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 @@ void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
|
||||
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[] = {
|
||||
|
||||
@@ -78,8 +78,8 @@ void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat);
|
||||
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 unregisterHealthApplicationNative(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__);
|
||||
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 @@ static JNINativeMethod sMethods[] = {
|
||||
|
||||
{"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},
|
||||
|
||||
Reference in New Issue
Block a user