summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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},
};