diff options
| author | 2011-02-11 12:40:44 -0800 | |
|---|---|---|
| committer | 2011-02-14 15:00:25 -0800 | |
| commit | a44a1e77ef435942b2ff60e9e60d3a64b43d775b (patch) | |
| tree | c9217816b765809422ab89947d6ebf2ff38e0b5d | |
| parent | 302b9884b3f0ecc96cc618643835d415e474cac3 (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.java | 105 | ||||
| -rw-r--r-- | core/jni/android_server_BluetoothService.cpp | 41 |
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}, }; |