summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jaikumar Ganesh <jaikumar@google.com> 2011-02-11 12:40:44 -0800
committer Jaikumar Ganesh <jaikumar@google.com> 2011-02-14 15:00:25 -0800
commita44a1e77ef435942b2ff60e9e60d3a64b43d775b (patch)
treec9217816b765809422ab89947d6ebf2ff38e0b5d
parent302b9884b3f0ecc96cc618643835d415e474cac3 (diff)
Distinguish between NAP and PAN role disconnections
Distinguish between NAP and PANU disconnect in BT tethering and call appropriate functions. We were never disconnecting NAP role devices. ToDo: BluetoothService needs to be refactored, its become too big 1) BluetoothAdapter and BluetoothDevice properties need to be moved to separate classes. 2) BluetoothPanProfile and BluetoothInputDeviceProfile which are handled by BluetoothService need to be moved to a separate file. 3) Integrate PAN to the profile state machine. Change-Id: I32a8d274f38c78931434bd9738c8f6570ba89fcf
-rw-r--r--core/java/android/server/BluetoothService.java105
-rw-r--r--core/jni/android_server_BluetoothService.cpp41
2 files changed, 125 insertions, 21 deletions
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index b6101b26bdea..2011175eaa7c 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -159,7 +159,7 @@ public class BluetoothService extends IBluetooth.Stub {
private BluetoothA2dpService mA2dpService;
private final HashMap<BluetoothDevice, Integer> mInputDevices;
- private final HashMap<BluetoothDevice, Pair<Integer, String>> mPanDevices;
+ private final HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;
private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0;
@@ -167,8 +167,6 @@ public class BluetoothService extends IBluetooth.Stub {
private static String mDockAddress;
private String mDockPin;
- private String mIface;
-
private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
private static class RemoteService {
@@ -250,7 +248,7 @@ public class BluetoothService extends IBluetooth.Stub {
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(mReceiver, filter);
mInputDevices = new HashMap<BluetoothDevice, Integer>();
- mPanDevices = new HashMap<BluetoothDevice, Pair<Integer, String>>();
+ mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
}
public static synchronized String readDockBluetoothAddress() {
@@ -1486,7 +1484,7 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized void setBluetoothTethering(boolean value) {
if (!value) {
- disconnectPan();
+ disconnectPanServerDevices();
}
if (getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
@@ -1511,11 +1509,11 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized int getPanDeviceState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- Pair<Integer, String> panDevice = mPanDevices.get(device);
+ BluetoothPanDevice panDevice = mPanDevices.get(device);
if (panDevice == null) {
return BluetoothPan.STATE_DISCONNECTED;
}
- return panDevice.first;
+ return panDevice.mState;
}
public synchronized boolean connectPanDevice(BluetoothDevice device) {
@@ -1552,14 +1550,28 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
- private synchronized boolean disconnectPan() {
+ private synchronized boolean disconnectPanServerDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) log("disconnect all PAN devices");
for (BluetoothDevice device: mPanDevices.keySet()) {
- if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
- if (!disconnectPanDevice(device)) {
- log ("could not disconnect Pan Device "+device.getAddress());
+ BluetoothPanDevice panDevice = mPanDevices.get(device);
+ int state = panDevice.mState;
+ if (state == BluetoothPan.STATE_CONNECTED &&
+ panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
+ String objectPath = getObjectPathFromAddress(device.getAddress());
+
+ handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
+ panDevice.mLocalRole);
+
+ if (!disconnectPanServerDeviceNative(objectPath, device.getAddress(),
+ panDevice.mIfaceAddr)) {
+ log ("could not disconnect Pan Server Device "+device.getAddress());
+
+ // Restore prev state
+ handlePanDeviceStateChange(device, state,
+ panDevice.mLocalRole);
+
return false;
}
}
@@ -1585,12 +1597,37 @@ public class BluetoothService extends IBluetooth.Stub {
"Need BLUETOOTH_ADMIN permission");
String objectPath = getObjectPathFromAddress(device.getAddress());
if (DBG) log("disconnect PAN(" + objectPath + ")");
- if (getPanDeviceState(device) != BluetoothPan.STATE_CONNECTED) {
+
+ int state = getPanDeviceState(device);
+ if (state != BluetoothPan.STATE_CONNECTED) {
log (device + " already disconnected from PAN");
+ return false;
}
+
+ BluetoothPanDevice panDevice = mPanDevices.get(device);
+
+ if (panDevice == null) {
+ log("No record for this Pan device:" + device);
+ return false;
+ }
+
handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
- BluetoothPan.LOCAL_PANU_ROLE);
- return disconnectPanDeviceNative(objectPath);
+ panDevice.mLocalRole);
+ if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
+ if (!disconnectPanServerDeviceNative(objectPath, device.getAddress(),
+ panDevice.mIface)) {
+ // Restore prev state, this shouldn't happen
+ handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+ return false;
+ }
+ } else {
+ if (!disconnectPanDeviceNative(objectPath)) {
+ // Restore prev state, this shouldn't happen
+ handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+ return false;
+ }
+ }
+ return true;
}
/*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
@@ -1599,12 +1636,13 @@ public class BluetoothService extends IBluetooth.Stub {
int role) {
int prevState;
String ifaceAddr = null;
+ BluetoothPanDevice panDevice = mPanDevices.get(device);
- if (mPanDevices.get(device) == null) {
+ if (panDevice == null) {
prevState = BluetoothPan.STATE_DISCONNECTED;
} else {
- prevState = mPanDevices.get(device).first;
- ifaceAddr = mPanDevices.get(device).second;
+ prevState = panDevice.mState;
+ ifaceAddr = panDevice.mIfaceAddr;
}
if (prevState == state) return;
@@ -1621,17 +1659,26 @@ public class BluetoothService extends IBluetooth.Stub {
} else {
// PANU Role = reverse Tether
if (state == BluetoothPan.STATE_CONNECTED) {
- mIface = iface;
BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
} else if (state == BluetoothPan.STATE_DISCONNECTED &&
(prevState == BluetoothPan.STATE_CONNECTED ||
prevState == BluetoothPan.STATE_DISCONNECTING)) {
- BluetoothTetheringDataTracker.getInstance().stopReverseTether(mIface);
+ BluetoothTetheringDataTracker.getInstance().stopReverseTether(panDevice.mIface);
}
}
- Pair<Integer, String> value = new Pair<Integer, String>(state, ifaceAddr);
- mPanDevices.put(device, value);
+ if (panDevice == null) {
+ panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, role);
+ mPanDevices.put(device, panDevice);
+ } else {
+ panDevice.mState = state;
+ panDevice.mIfaceAddr = ifaceAddr;
+ panDevice.mLocalRole = role;
+ }
+
+ if (state == BluetoothPan.STATE_DISCONNECTED) {
+ mPanDevices.remove(device);
+ }
Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
@@ -1649,6 +1696,20 @@ public class BluetoothService extends IBluetooth.Stub {
handlePanDeviceStateChange(device, null, state, role);
}
+ private class BluetoothPanDevice {
+ private int mState;
+ private String mIfaceAddr;
+ private String mIface;
+ private int mLocalRole; // Which local role is this PAN device bound too
+
+ BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
+ mState = state;
+ mIfaceAddr = ifaceAddr;
+ mIface = iface;
+ mLocalRole = localRole;
+ }
+ }
+
private String createNewTetheringAddressLocked() {
if (getConnectedPanDevices().size() == mMaxPanDevices) {
log("Max PAN device connections reached");
@@ -2933,6 +2994,8 @@ public class BluetoothService extends IBluetooth.Stub {
private native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
private native boolean connectPanDeviceNative(String path, String dstRole);
private native boolean disconnectPanDeviceNative(String path);
+ private native boolean disconnectPanServerDeviceNative(String path,
+ String address, String iface);
private native int[] addReservedServiceRecordsNative(int[] uuuids);
private native boolean removeReservedServiceRecordsNative(int[] handles);
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 2c398713295b..bf0504f7c8cc 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1214,6 +1214,45 @@ static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object,
return JNI_FALSE;
}
+static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object,
+ jstring path, jstring address,
+ jstring iface) {
+ LOGV(__FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ LOGE("disconnectPanServerDeviceNative");
+ 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 && eventLoopNat) {
+ const char *c_address = env->GetStringUTFChars(address, NULL);
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ const char *c_iface = env->GetStringUTFChars(iface, NULL);
+
+ int len = env->GetStringLength(path) + 1;
+ char *context_path = (char *)calloc(len, sizeof(char));
+ strlcpy(context_path, c_path, len); // for callback
+
+ bool ret = dbus_func_args_async(env, nat->conn, -1,
+ onPanDeviceConnectionResult,
+ context_path, eventLoopNat,
+ get_adapter_path(env, object),
+ DBUS_NETWORKSERVER_IFACE,
+ "DisconnectDevice",
+ DBUS_TYPE_STRING, &c_address,
+ DBUS_TYPE_STRING, &c_iface,
+ DBUS_TYPE_INVALID);
+
+ env->ReleaseStringUTFChars(address, c_address);
+ env->ReleaseStringUTFChars(iface, c_iface);
+ env->ReleaseStringUTFChars(path, c_path);
+ return ret ? JNI_TRUE : JNI_FALSE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void*)classInitNative},
@@ -1274,6 +1313,8 @@ static JNINativeMethod sMethods[] = {
{"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
(void *)connectPanDeviceNative},
{"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
+ {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+ (void *)disconnectPanServerDeviceNative},
};