summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNitin Arora <niarora@codeaurora.org>2015-03-11 15:45:26 -0700
committerAndre Eisenbach <eisenbach@google.com>2015-04-15 23:30:10 -0700
commitf19f1ac64a5fefb248ab15b918d009b926c99dde (patch)
tree8b5e76134add97468a8d4801fb51d12dd5573003
parentdbe4c2517804b3e32587310b76f1c977b8749d8b (diff)
downloadandroid_packages_apps_Bluetooth-f19f1ac64a5fefb248ab15b918d009b926c99dde.tar.gz
android_packages_apps_Bluetooth-f19f1ac64a5fefb248ab15b918d009b926c99dde.tar.bz2
android_packages_apps_Bluetooth-f19f1ac64a5fefb248ab15b918d009b926c99dde.zip
Bluetooth LE background operation mode (1/2)
Changes to BluetoothAdapter state machine for handling new states BLE_STATE_ON and intermediate states BLE_TURNING_ON and BLE_TURNING_OFF. Also includes the actions required while migrating in and out of these states including start and stop of GATT services and other profiles. Change-Id: I08d6ff05c2cefe559d5bb5789a1a488afefbe544
-rw-r--r--jni/com_android_bluetooth_avrcp.cpp47
-rw-r--r--[-rwxr-xr-x]jni/com_android_bluetooth_hid.cpp0
-rw-r--r--jni/com_android_bluetooth_pan.cpp9
-rw-r--r--src/com/android/bluetooth/btservice/AdapterProperties.java14
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java183
-rw-r--r--[-rwxr-xr-x]src/com/android/bluetooth/btservice/AdapterState.java312
-rw-r--r--src/com/android/bluetooth/btservice/ProfileService.java5
-rw-r--r--src/com/android/bluetooth/btservice/RemoteDevices.java20
-rw-r--r--src/com/android/bluetooth/gatt/ContextMap.java13
-rw-r--r--src/com/android/bluetooth/gatt/GattService.java31
-rwxr-xr-xsrc/com/android/bluetooth/hid/HidService.java2
11 files changed, 493 insertions, 143 deletions
diff --git a/jni/com_android_bluetooth_avrcp.cpp b/jni/com_android_bluetooth_avrcp.cpp
index e9a7bc90d..b28a43e30 100644
--- a/jni/com_android_bluetooth_avrcp.cpp
+++ b/jni/com_android_bluetooth_avrcp.cpp
@@ -59,13 +59,18 @@ static void btavrcp_remote_features_callback(bt_bdaddr_t* bd_addr, btrc_remote_f
}
addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
if (!addr) {
- ALOGE("Fail to new jbyteArray bd addr for connection state");
+ ALOGE("Unable to allocate byte array for bd_addr");
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
return;
}
- sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getRcFeatures, addr, (jint)features);
+ if (mCallbacksObj) {
+ sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getRcFeatures, addr, (jint)features);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
/* TODO: I think we leak the addr object, we should add a
* sCallbackEnv->DeleteLocalRef(addr) */
@@ -79,7 +84,11 @@ static void btavrcp_get_play_status_callback() {
return;
}
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus);
+ if (mCallbacksObj) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
@@ -99,7 +108,11 @@ static void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_
return;
}
sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs);
+ if (mCallbacksObj) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(attrs);
}
@@ -111,9 +124,12 @@ static void btavrcp_register_notification_callback(btrc_event_id_t event_id, uin
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
return;
}
-
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification,
+ if (mCallbacksObj) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification,
(jint)event_id, (jint)param);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
@@ -124,9 +140,13 @@ static void btavrcp_volume_change_callback(uint8_t volume, uint8_t ctype) {
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
return;
}
+ if (mCallbacksObj) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_volumeChangeCallback, (jint)volume,
+ (jint)ctype);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_volumeChangeCallback, (jint)volume,
- (jint)ctype);
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
@@ -137,9 +157,12 @@ static void btavrcp_passthrough_command_callback(int id, int pressed) {
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
return;
}
-
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd, (jint)id,
- (jint)pressed);
+ if (mCallbacksObj) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd,
+ (jint)id, (jint)pressed);
+ } else {
+ ALOGE("%s: mCallbacksObj is null", __FUNCTION__);
+ }
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
diff --git a/jni/com_android_bluetooth_hid.cpp b/jni/com_android_bluetooth_hid.cpp
index adff0f58a..adff0f58a 100755..100644
--- a/jni/com_android_bluetooth_hid.cpp
+++ b/jni/com_android_bluetooth_hid.cpp
diff --git a/jni/com_android_bluetooth_pan.cpp b/jni/com_android_bluetooth_pan.cpp
index 500fd91e6..d2b2f6e05 100644
--- a/jni/com_android_bluetooth_pan.cpp
+++ b/jni/com_android_bluetooth_pan.cpp
@@ -134,14 +134,19 @@ static void initializeNative(JNIEnv *env, jobject object) {
return;
}
+ mCallbacksObj = env->NewGlobalRef(object);
+
bt_status_t status;
if ( (status = sPanIf->init(&sBluetoothPanCallbacks)) != BT_STATUS_SUCCESS) {
error("Failed to initialize Bluetooth PAN, status: %d", status);
sPanIf = NULL;
+ if (mCallbacksObj != NULL) {
+ ALOGW("initialization failed: Cleaning up Bluetooth PAN callback object");
+ env->DeleteGlobalRef(mCallbacksObj);
+ mCallbacksObj = NULL;
+ }
return;
}
-
- mCallbacksObj = env->NewGlobalRef(object);
}
static void cleanupNative(JNIEnv *env, jobject object) {
diff --git a/src/com/android/bluetooth/btservice/AdapterProperties.java b/src/com/android/bluetooth/btservice/AdapterProperties.java
index 7e550a7e2..b86faafbb 100644
--- a/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -604,9 +604,20 @@ class AdapterProperties {
}
}
- private boolean mBluetoothDisabling=false;
+ private boolean mBluetoothDisabling = false;
+
+ void onBleDisable() {
+ // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state.
+ // When BT disable is invoked, set the scan_mode to NONE
+ // so no incoming connections are possible
+ debugLog("onBleDisable");
+ if (getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
+ setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
+ }
+ }
void onBluetoothDisable() {
+ // From STATE_ON to BLE_ON
// When BT disable is invoked, set the scan_mode to NONE
// so no incoming connections are possible
@@ -618,6 +629,7 @@ class AdapterProperties {
setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
}
}
+
void discoveryStateChangeCallback(int state) {
infoLog("Callback:discoveryStateChangeCallback with state:" + state);
synchronized (mObject) {
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index c78adf0b3..f16f082db 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -81,7 +81,7 @@ import android.os.ServiceManager;
public class AdapterService extends Service {
private static final String TAG = "BluetoothAdapterService";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final boolean TRACE_REF = true;
private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
private static final int MIN_OFFLOADED_FILTERS = 10;
@@ -287,6 +287,8 @@ public class AdapterService extends Service {
private void processProfileServiceStateChanged(String serviceName, int state) {
boolean doUpdate=false;
+ boolean isBleTurningOn;
+ boolean isBleTurningOff;
boolean isTurningOn;
boolean isTurningOff;
@@ -307,15 +309,41 @@ public class AdapterService extends Service {
synchronized (mAdapterStateMachine) {
isTurningOff = mAdapterStateMachine.isTurningOff();
isTurningOn = mAdapterStateMachine.isTurningOn();
+ isBleTurningOn = mAdapterStateMachine.isBleTurningOn();
+ isBleTurningOff = mAdapterStateMachine.isBleTurningOff();
}
- if (isTurningOff) {
+ debugLog("processProfileServiceStateChanged() - serviceName=" + serviceName +
+ " isTurningOn=" + isTurningOn + " isTurningOff=" + isTurningOff +
+ " isBleTurningOn=" + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff);
+
+ if (isBleTurningOn) {
+ if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
+ debugLog("GattService is started");
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));
+ return;
+ }
+
+ } else if(isBleTurningOff) {
+ if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
+ debugLog("GattService stopped");
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED));
+ return;
+ }
+
+ } else if (isTurningOff) {
+ //On to BLE_ON
//Process stop or disable pending
//Check if all services are stopped if so, do cleanup
synchronized (mProfileServicesState) {
Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
while (i.hasNext()) {
Map.Entry<String,Integer> entry = i.next();
+ debugLog("Service: " + entry.getKey());
+ if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) {
+ debugLog("Skip GATT service - already started before");
+ continue;
+ }
if (BluetoothAdapter.STATE_OFF != entry.getValue()) {
debugLog("onProfileServiceStateChange() - Profile still running: "
+ entry.getKey());
@@ -326,7 +354,8 @@ public class AdapterService extends Service {
debugLog("onProfileServiceStateChange() - All profile services stopped...");
//Send message to state machine
mProfilesStarted=false;
- mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED));
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED));
+
} else if (isTurningOn) {
//Process start pending
//Check if all services are started if so, update state
@@ -334,6 +363,11 @@ public class AdapterService extends Service {
Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
while (i.hasNext()) {
Map.Entry<String,Integer> entry = i.next();
+ debugLog("Service: " + entry.getKey());
+ if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) {
+ debugLog("Skip GATT service - already started before");
+ continue;
+ }
if (BluetoothAdapter.STATE_ON != entry.getValue()) {
debugLog("onProfileServiceStateChange() - Profile still not running:"
+ entry.getKey());
@@ -344,7 +378,7 @@ public class AdapterService extends Service {
debugLog("onProfileServiceStateChange() - All profile services started.");
mProfilesStarted=true;
//Send message to state machine
- mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
}
}
@@ -387,8 +421,8 @@ public class AdapterService extends Service {
debugLog("onDestroy()");
}
- void processStart() {
- debugLog("processStart()");
+ void BleOnProcessStart() {
+ debugLog("BleOnProcessStart()");
Class[] supportedProfileServices = Config.getSupportedProfiles();
//Initialize data objects
for (int i=0; i < supportedProfileServices.length;i++) {
@@ -397,7 +431,7 @@ public class AdapterService extends Service {
mRemoteDevices = new RemoteDevices(this);
mAdapterProperties.init(mRemoteDevices);
- debugLog("processStart() - Make Bond State Machine");
+ debugLog("BleOnProcessStart() - Make Bond State Machine");
mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
@@ -405,13 +439,22 @@ public class AdapterService extends Service {
//FIXME: Set static instance here???
setAdapterService(this);
+ //Start Gatt service
+ setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
+ }
+
+ void startCoreServices()
+ {
+ debugLog("startCoreServices()");
+ Class[] supportedProfileServices = Config.getSupportedProfiles();
+
//Start profile services
if (!mProfilesStarted && supportedProfileServices.length >0) {
//Startup all profile services
setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}else {
- debugLog("processStart() - Profile Services alreay started");
- mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
+ debugLog("startCoreProfiles(): Profile Services alreay started");
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
}
}
@@ -429,6 +472,16 @@ public class AdapterService extends Service {
return false;
}
+ boolean stopGattProfileService() {
+ //TODO: can optimize this instead of looping around all supported profiles
+ debugLog("stopGattProfileService()");
+ Class[] supportedProfileServices = Config.getSupportedProfiles();
+
+ setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
+ return true;
+ }
+
+
void updateAdapterState(int prevState, int newState){
if (mCallbacks !=null) {
int n=mCallbacks.beginBroadcast();
@@ -517,7 +570,6 @@ public class AdapterService extends Service {
mCallbacks.kill();
}
- debugLog("cleanup() - Bluetooth process exited normally.");
System.exit(0);
}
@@ -563,6 +615,51 @@ public class AdapterService extends Service {
};
@SuppressWarnings("rawtypes")
+ private void setGattProfileServiceState(Class[] services, int state) {
+ if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
+ Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");
+ return;
+ }
+
+ int expectedCurrentState= BluetoothAdapter.STATE_OFF;
+ int pendingState = BluetoothAdapter.STATE_TURNING_ON;
+
+ if (state == BluetoothAdapter.STATE_OFF) {
+ expectedCurrentState= BluetoothAdapter.STATE_ON;
+ pendingState = BluetoothAdapter.STATE_TURNING_OFF;
+ }
+
+ for (int i=0; i <services.length;i++) {
+ String serviceName = services[i].getName();
+ String simpleName = services[i].getSimpleName();
+
+ if (simpleName.equals("GattService")) {
+ if (DBG) Log.d(TAG, "It is gaTT service");
+ Integer serviceState = mProfileServicesState.get(serviceName);
+
+ if(serviceState != null && serviceState != expectedCurrentState) {
+ debugLog("setProfileServiceState() - Unable to "
+ + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
+ + " service " + serviceName
+ + ". Invalid state: " + serviceState);
+ continue;
+ }
+ debugLog("setProfileServiceState() - "
+ + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
+ + " service " + serviceName);
+
+ mProfileServicesState.put(serviceName,pendingState);
+ Intent intent = new Intent(this,services[i]);
+ intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
+ intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
+ startService(intent);
+ return;
+ }
+ }
+ }
+
+
+ @SuppressWarnings("rawtypes")
private void setProfileServiceState(Class[] services, int state) {
if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
debugLog("setProfileServiceState() - Invalid state, leaving...");
@@ -578,6 +675,12 @@ public class AdapterService extends Service {
for (int i=0; i <services.length;i++) {
String serviceName = services[i].getName();
+ String simpleName = services[i].getSimpleName();
+
+ if (simpleName.equals("GattService")) {
+ if (DBG) Log.d(TAG, "It is gaTT service. SKIP IT");
+ continue;
+ }
Integer serviceState = mProfileServicesState.get(serviceName);
if(serviceState != null && serviceState != expectedCurrentState) {
debugLog("setProfileServiceState() - Unable to "
@@ -1158,54 +1261,56 @@ public class AdapterService extends Service {
}
return service.dump();
}
+
+ public void onLeServiceUp(){
+ AdapterService service = getService();
+ if (service == null) return;
+ service.onLeServiceUp();
+ }
+
+ public void onBrEdrDown(){
+ AdapterService service = getService();
+ if (service == null) return;
+ service.onBrEdrDown();
+ }
};
+ // ----API Methods--------
- //----API Methods--------
boolean isEnabled() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
- }
+ }
int getState() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
- if (mAdapterProperties == null){
- return BluetoothAdapter.STATE_OFF;
- }
- else {
- debugLog("getState() - mAdapterProperties: " + mAdapterProperties);
- return mAdapterProperties.getState();
- }
- }
+ if (mAdapterProperties != null) return mAdapterProperties.getState();
+ return BluetoothAdapter.STATE_OFF;
+ }
boolean enable() {
return enable (false);
- }
+ }
public boolean enableNoAutoConnect() {
return enable (true);
}
public synchronized boolean enable(boolean quietMode) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
+
debugLog("enable() - Enable called with quiet mode status = " + mQuietmode);
- mQuietmode = quietMode;
- Message m =
- mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
+ mQuietmode = quietMode;
+ Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
mAdapterStateMachine.sendMessage(m);
return true;
}
boolean disable() {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
debugLog("disable() called...");
- Message m =
- mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
+ Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
mAdapterStateMachine.sendMessage(m);
return true;
}
@@ -1755,6 +1860,16 @@ public class AdapterService extends Service {
return sb.toString();
}
+ public void onLeServiceUp() {
+ Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
+ mAdapterStateMachine.sendMessage(m);
+ }
+
+ public void onBrEdrDown() {
+ Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
+ mAdapterStateMachine.sendMessage(m);
+ }
+
private static int convertScanModeToHal(int mode) {
switch (mode) {
case BluetoothAdapter.SCAN_MODE_NONE:
@@ -1888,11 +2003,11 @@ public class AdapterService extends Service {
}
private void debugLog(String msg) {
- if (DBG) Log.d(TAG +"(" +hashCode()+")", msg);
+ if (DBG) Log.d(TAG, msg);
}
private void errorLog(String msg) {
- Log.e(TAG +"(" +hashCode()+")", msg);
+ Log.e(TAG, msg);
}
private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() {
diff --git a/src/com/android/bluetooth/btservice/AdapterState.java b/src/com/android/bluetooth/btservice/AdapterState.java
index 5f9c30bf4..38db5dbed 100755..100644
--- a/src/com/android/bluetooth/btservice/AdapterState.java
+++ b/src/com/android/bluetooth/btservice/AdapterState.java
@@ -37,55 +37,79 @@ import com.android.internal.util.StateMachine;
final class AdapterState extends StateMachine {
private static final boolean DBG = true;
- private static final boolean VDBG = false;
+ private static final boolean VDBG = true;
private static final String TAG = "BluetoothAdapterState";
+ static final int BLE_TURN_ON = 0;
static final int USER_TURN_ON = 1;
- static final int STARTED=2;
+ static final int BREDR_STARTED=2;
static final int ENABLED_READY = 3;
+ static final int BLE_STARTED=4;
static final int USER_TURN_OFF = 20;
static final int BEGIN_DISABLE = 21;
static final int ALL_DEVICES_DISCONNECTED = 22;
+ static final int BLE_TURN_OFF = 23;
static final int DISABLED = 24;
- static final int STOPPED=25;
+ static final int BLE_STOPPED=25;
+ static final int BREDR_STOPPED = 26;
- static final int START_TIMEOUT = 100;
+ static final int BREDR_START_TIMEOUT = 100;
static final int ENABLE_TIMEOUT = 101;
static final int DISABLE_TIMEOUT = 103;
- static final int STOP_TIMEOUT = 104;
+ static final int BLE_STOP_TIMEOUT = 104;
static final int SET_SCAN_MODE_TIMEOUT = 105;
+ static final int BLE_START_TIMEOUT = 106;
+ static final int BREDR_STOP_TIMEOUT = 107;
static final int USER_TURN_OFF_DELAY_MS=500;
//TODO: tune me
- private static final int ENABLE_TIMEOUT_DELAY = 8000;
+ private static final int ENABLE_TIMEOUT_DELAY = 12000;
private static final int DISABLE_TIMEOUT_DELAY = 8000;
- private static final int START_TIMEOUT_DELAY = 5000;
- private static final int STOP_TIMEOUT_DELAY = 5000;
+ private static final int BREDR_START_TIMEOUT_DELAY = 4000;
+ //BLE_START_TIMEOUT can happen quickly as it just a start gattservice
+ private static final int BLE_START_TIMEOUT_DELAY = 2000; //To start GattService
+ private static final int BLE_STOP_TIMEOUT_DELAY = 2000;
+ //BREDR_STOP_TIMEOUT can < STOP_TIMEOUT
+ private static final int BREDR_STOP_TIMEOUT_DELAY = 4000;
private static final int PROPERTY_OP_DELAY =2000;
private AdapterService mAdapterService;
private AdapterProperties mAdapterProperties;
private PendingCommandState mPendingCommandState = new PendingCommandState();
private OnState mOnState = new OnState();
private OffState mOffState = new OffState();
+ private BleOnState mBleOnState = new BleOnState();
public boolean isTurningOn() {
boolean isTurningOn= mPendingCommandState.isTurningOn();
- if (VDBG) Log.d(TAG,"isTurningOn()=" + isTurningOn);
+ verboseLog("isTurningOn()=" + isTurningOn);
return isTurningOn;
}
+ public boolean isBleTurningOn() {
+ boolean isBleTurningOn= mPendingCommandState.isBleTurningOn();
+ verboseLog("isBleTurningOn()=" + isBleTurningOn);
+ return isBleTurningOn;
+ }
+
+ public boolean isBleTurningOff() {
+ boolean isBleTurningOff = mPendingCommandState.isBleTurningOff();
+ verboseLog("isBleTurningOff()=" + isBleTurningOff);
+ return isBleTurningOff;
+ }
+
public boolean isTurningOff() {
boolean isTurningOff= mPendingCommandState.isTurningOff();
- if (VDBG) Log.d(TAG,"isTurningOff()=" + isTurningOff);
+ verboseLog("isTurningOff()=" + isTurningOff);
return isTurningOff;
}
private AdapterState(AdapterService service, AdapterProperties adapterProperties) {
super("BluetoothAdapterState:");
addState(mOnState);
+ addState(mBleOnState);
addState(mOffState);
addState(mPendingCommandState);
mAdapterService = service;
@@ -94,7 +118,7 @@ final class AdapterState extends StateMachine {
}
public static AdapterState make(AdapterService service, AdapterProperties adapterProperties) {
- Log.d(TAG, "make");
+ Log.d(TAG, "make() - Creating AdapterState");
AdapterState as = new AdapterState(service, adapterProperties);
as.start();
return as;
@@ -121,25 +145,76 @@ final class AdapterState extends StateMachine {
public boolean processMessage(Message msg) {
AdapterService adapterService = mAdapterService;
if (adapterService == null) {
- Log.e(TAG,"receive message at OffState after cleanup:" +
- msg.what);
+ errorLog("Received message in OffState after cleanup: " + msg.what);
return false;
}
+
+ debugLog("Current state: OFF, message: " + msg.what);
+
+ switch(msg.what) {
+ case BLE_TURN_ON:
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
+ mPendingCommandState.setBleTurningOn(true);
+ transitionTo(mPendingCommandState);
+ sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
+ adapterService.BleOnProcessStart();
+ break;
+
+ case USER_TURN_OFF:
+ //TODO: Handle case of service started and stopped without enable
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private class BleOnState extends State {
+ @Override
+ public void enter() {
+ infoLog("Entering BleOnState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+
+ AdapterService adapterService = mAdapterService;
+ AdapterProperties adapterProperties = mAdapterProperties;
+ if ((adapterService == null) || (adapterProperties == null)) {
+ errorLog("Received message in BleOnState after cleanup: " + msg.what);
+ return false;
+ }
+
+ debugLog("Current state: BLE ON, message: " + msg.what);
+
switch(msg.what) {
case USER_TURN_ON:
- if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
mPendingCommandState.setTurningOn(true);
transitionTo(mPendingCommandState);
- sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);
- adapterService.processStart();
+ sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
+ adapterService.startCoreServices();
break;
+
case USER_TURN_OFF:
- if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF");
- //TODO: Handle case of service started and stopped without enable
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF);
+ mPendingCommandState.setBleTurningOff(true);
+ adapterProperties.onBleDisable();
+ transitionTo(mPendingCommandState);
+ sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY);
+ boolean ret = adapterService.disableNative();
+ if (!ret) {
+ removeMessages(DISABLE_TIMEOUT);
+ errorLog("Error while calling disableNative");
+ //FIXME: what about post enable services
+ mPendingCommandState.setBleTurningOff(false);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
+ }
break;
+
default:
- if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=OFF, MESSAGE = " + msg.what );
return false;
}
return true;
@@ -149,10 +224,11 @@ final class AdapterState extends StateMachine {
private class OnState extends State {
@Override
public void enter() {
- infoLog("Entering On State");
+ infoLog("Entering OnState");
+
AdapterService adapterService = mAdapterService;
if (adapterService == null) {
- Log.e(TAG,"enter OnState after cleanup");
+ errorLog("Entered OnState after cleanup");
return;
}
adapterService.autoConnect();
@@ -162,14 +238,14 @@ final class AdapterState extends StateMachine {
public boolean processMessage(Message msg) {
AdapterProperties adapterProperties = mAdapterProperties;
if (adapterProperties == null) {
- Log.e(TAG,"receive message at OnState after cleanup:" +
- msg.what);
+ errorLog("Received message in OnState after cleanup: " + msg.what);
return false;
}
+ debugLog("Current state: ON, message: " + msg.what);
+
switch(msg.what) {
- case USER_TURN_OFF:
- if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_OFF");
+ case BLE_TURN_OFF:
notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
mPendingCommandState.setTurningOff(true);
transitionTo(mPendingCommandState);
@@ -182,11 +258,9 @@ final class AdapterState extends StateMachine {
break;
case USER_TURN_ON:
- if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_ON");
- Log.i(TAG,"Bluetooth already ON, ignoring USER_TURN_ON");
break;
+
default:
- if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=ON, MESSAGE = " + msg.what );
return false;
}
return true;
@@ -196,9 +270,11 @@ final class AdapterState extends StateMachine {
private class PendingCommandState extends State {
private boolean mIsTurningOn;
private boolean mIsTurningOff;
+ private boolean mIsBleTurningOn;
+ private boolean mIsBleTurningOff;
public void enter() {
- infoLog("Entering PendingCommandState State: isTurningOn()=" + isTurningOn() + ", isTurningOff()=" + isTurningOff());
+ infoLog("Entering PendingCommandState");
}
public void setTurningOn(boolean isTurningOn) {
@@ -217,89 +293,111 @@ final class AdapterState extends StateMachine {
return mIsTurningOff;
}
+ public void setBleTurningOn(boolean isBleTurningOn) {
+ mIsBleTurningOn = isBleTurningOn;
+ }
+
+ public boolean isBleTurningOn() {
+ return mIsBleTurningOn;
+ }
+
+ public void setBleTurningOff(boolean isBleTurningOff) {
+ mIsBleTurningOff = isBleTurningOff;
+ }
+
+ public boolean isBleTurningOff() {
+ return mIsBleTurningOff;
+ }
+
@Override
public boolean processMessage(Message msg) {
boolean isTurningOn= isTurningOn();
boolean isTurningOff = isTurningOff();
+ boolean isBleTurningOn = isBleTurningOn();
+ boolean isBleTurningOff = isBleTurningOff();
AdapterService adapterService = mAdapterService;
AdapterProperties adapterProperties = mAdapterProperties;
if ((adapterService == null) || (adapterProperties == null)) {
- Log.e(TAG,"receive message at Pending State after cleanup:" +
- msg.what);
+ errorLog("Received message in PendingCommandState after cleanup: " + msg.what);
return false;
}
+ debugLog("Current state: PENDING_COMMAND, message: " + msg.what);
+
switch (msg.what) {
case USER_TURN_ON:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
- + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- if (isTurningOn) {
- Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning on bluetooth... Ignoring USER_TURN_ON...");
- } else {
- Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_ON");
+ if (isBleTurningOff || isTurningOff) { //TODO:do we need to send it after ble turn off also??
+ infoLog("Deferring USER_TURN_ON request...");
deferMessage(msg);
}
break;
+
case USER_TURN_OFF:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
- + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- if (isTurningOff) {
- Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning off bluetooth... Ignoring USER_TURN_OFF...");
- } else {
- Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_OFF");
+ if (isTurningOn || isBleTurningOn) {
+ infoLog("Deferring USER_TURN_OFF request...");
+ deferMessage(msg);
+ }
+ break;
+
+ case BLE_TURN_ON:
+ if (isTurningOff || isBleTurningOff) {
+ infoLog("Deferring BLE_TURN_ON request...");
+ deferMessage(msg);
+ }
+ break;
+
+ case BLE_TURN_OFF:
+ if (isTurningOn || isBleTurningOn) {
+ infoLog("Deferring BLE_TURN_OFF request...");
deferMessage(msg);
}
break;
- case STARTED: {
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
+
+ case BLE_STARTED:
//Remove start timeout
- removeMessages(START_TIMEOUT);
+ removeMessages(BLE_START_TIMEOUT);
//Enable
- boolean ret = adapterService.enableNative();
- if (!ret) {
- Log.e(TAG, "Error while turning Bluetooth On");
+ if (!adapterService.enableNative()) {
+ errorLog("Error while turning Bluetooth on");
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
transitionTo(mOffState);
} else {
sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
}
- }
break;
- case ENABLED_READY:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_READY, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- removeMessages(ENABLE_TIMEOUT);
+ case BREDR_STARTED:
+ //Remove start timeout
+ removeMessages(BREDR_START_TIMEOUT);
adapterProperties.onBluetoothReady();
mPendingCommandState.setTurningOn(false);
transitionTo(mOnState);
notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
break;
+ case ENABLED_READY:
+ removeMessages(ENABLE_TIMEOUT);
+ mPendingCommandState.setBleTurningOn(false);
+ transitionTo(mBleOnState);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
+ break;
+
case SET_SCAN_MODE_TIMEOUT:
- Log.w(TAG,"Timeout will setting scan mode..Continuing with disable...");
+ warningLog("Timeout while setting scan mode. Continuing with disable...");
//Fall through
- case BEGIN_DISABLE: {
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = BEGIN_DISABLE, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
+ case BEGIN_DISABLE:
removeMessages(SET_SCAN_MODE_TIMEOUT);
- sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY);
- boolean ret = adapterService.disableNative();
- if (!ret) {
- removeMessages(DISABLE_TIMEOUT);
- Log.e(TAG, "Error while turning Bluetooth Off");
- //FIXME: what about post enable services
- mPendingCommandState.setTurningOff(false);
- notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
- }
- }
+ sendMessageDelayed(BREDR_STOP_TIMEOUT, BREDR_STOP_TIMEOUT_DELAY);
+ adapterService.stopProfileServices();
break;
+
case DISABLED:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
if (isTurningOn) {
removeMessages(ENABLE_TIMEOUT);
- errorLog("Error enabling Bluetooth - hardware init failed");
+ errorLog("Error enabling Bluetooth - hardware init failed?");
mPendingCommandState.setTurningOn(false);
transitionTo(mOffState);
adapterService.stopProfileServices();
@@ -307,60 +405,80 @@ final class AdapterState extends StateMachine {
break;
}
removeMessages(DISABLE_TIMEOUT);
- sendMessageDelayed(STOP_TIMEOUT, STOP_TIMEOUT_DELAY);
- if (adapterService.stopProfileServices()) {
- Log.d(TAG,"Stopping profile services that were post enabled");
+ sendMessageDelayed(BLE_STOP_TIMEOUT, BLE_STOP_TIMEOUT_DELAY);
+ if (adapterService.stopGattProfileService()) {
+ debugLog("Stopping Gatt profile services that were post enabled");
break;
}
//Fall through if no services or services already stopped
- case STOPPED:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOPPED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- removeMessages(STOP_TIMEOUT);
- setTurningOff(false);
+ case BLE_STOPPED:
+ removeMessages(BLE_STOP_TIMEOUT);
+ setBleTurningOff(false);
transitionTo(mOffState);
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
break;
- case START_TIMEOUT:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = START_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- errorLog("Error enabling Bluetooth");
- mPendingCommandState.setTurningOn(false);
+
+ case BREDR_STOPPED:
+ removeMessages(BREDR_STOP_TIMEOUT);
+ setTurningOff(false);
+ transitionTo(mBleOnState);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
+ break;
+
+ case BLE_START_TIMEOUT:
+ errorLog("Error enabling Bluetooth (BLE start timeout)");
+ mPendingCommandState.setBleTurningOn(false);
transitionTo(mOffState);
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
break;
- case ENABLE_TIMEOUT:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- errorLog("Error enabling Bluetooth");
+
+ case BREDR_START_TIMEOUT:
+ errorLog("Error enabling Bluetooth (start timeout)");
mPendingCommandState.setTurningOn(false);
+ transitionTo(mBleOnState);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
+ break;
+
+ case ENABLE_TIMEOUT:
+ errorLog("Error enabling Bluetooth (enable timeout)");
+ mPendingCommandState.setBleTurningOn(false);
transitionTo(mOffState);
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
break;
- case STOP_TIMEOUT:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOP_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- errorLog("Error stopping Bluetooth profiles");
+
+ case BREDR_STOP_TIMEOUT:
+ errorLog("Error stopping Bluetooth profiles (stop timeout)");
+ mPendingCommandState.setTurningOff(false);
+ transitionTo(mBleOnState);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
+ break;
+
+ case BLE_STOP_TIMEOUT:
+ errorLog("Error stopping Bluetooth profiles (BLE stop timeout)");
mPendingCommandState.setTurningOff(false);
transitionTo(mOffState);
+ notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
break;
+
case DISABLE_TIMEOUT:
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- errorLog("Error disabling Bluetooth");
+ errorLog("Error disabling Bluetooth (disable timeout)");
mPendingCommandState.setTurningOff(false);
transitionTo(mOnState);
notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
break;
+
default:
- if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=PENDING, MESSAGE = " + msg.what );
return false;
}
return true;
}
}
-
private void notifyAdapterStateChange(int newState) {
AdapterService adapterService = mAdapterService;
AdapterProperties adapterProperties = mAdapterProperties;
if ((adapterService == null) || (adapterProperties == null)) {
- Log.e(TAG,"notifyAdapterStateChange after cleanup:" + newState);
+ errorLog("notifyAdapterStateChange after cleanup:" + newState);
return;
}
@@ -373,9 +491,11 @@ final class AdapterState extends StateMachine {
void stateChangeCallback(int status) {
if (status == AbstractionLayer.BT_STATE_OFF) {
sendMessage(DISABLED);
+
} else if (status == AbstractionLayer.BT_STATE_ON) {
// We should have got the property change for adapter and remote devices.
sendMessage(ENABLED_READY);
+
} else {
errorLog("Incorrect status in stateChangeCallback");
}
@@ -385,6 +505,18 @@ final class AdapterState extends StateMachine {
if (DBG) Log.i(TAG, msg);
}
+ private void debugLog(String msg) {
+ if (DBG) Log.d(TAG, msg);
+ }
+
+ private void warningLog(String msg) {
+ if (DBG) Log.d(TAG, msg);
+ }
+
+ private void verboseLog(String msg) {
+ if (VDBG) Log.v(TAG, msg);
+ }
+
private void errorLog(String msg) {
Log.e(TAG, msg);
}
diff --git a/src/com/android/bluetooth/btservice/ProfileService.java b/src/com/android/bluetooth/btservice/ProfileService.java
index 1b70944ae..1e332bb69 100644
--- a/src/com/android/bluetooth/btservice/ProfileService.java
+++ b/src/com/android/bluetooth/btservice/ProfileService.java
@@ -231,7 +231,10 @@ public abstract class ProfileService extends Service {
}
protected BluetoothDevice getDevice(byte[] address) {
- return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
+ if(mAdapter != null){
+ return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
+ }
+ return null;
}
protected void log(String msg) {
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index e49b48632..3a9fd1c64 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -323,6 +323,8 @@ final class RemoteDevices {
errorLog("aclStateChangeCallback: Device is NULL");
return;
}
+ int state = mAdapterService.getState();
+ Log.e(TAG, "state" + state + "newState" + newState);
DeviceProperties prop = getDeviceProperties(device);
if (prop == null) {
@@ -330,10 +332,24 @@ final class RemoteDevices {
}
Intent intent = null;
if (newState == AbstractionLayer.BT_ACL_STATE_CONNECTED) {
- intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
+ if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_ON) {
+ intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
+ } else if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON) {
+ intent = new Intent(BluetoothAdapter.ACTION_BLE_ACL_CONNECTED);
+ }
debugLog("aclStateChangeCallback: State:Connected to Device:" + device);
} else {
- intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
+ /*Broadcasting PAIRING_CANCEL intent as well in this case*/
+ intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
+ }
+ if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_OFF) {
+ intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ } else if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
+ intent = new Intent(BluetoothAdapter.ACTION_BLE_ACL_DISCONNECTED);
+ }
debugLog("aclStateChangeCallback: State:DisConnected to Device:" + device);
}
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
diff --git a/src/com/android/bluetooth/gatt/ContextMap.java b/src/com/android/bluetooth/gatt/ContextMap.java
index 1b40bc0d8..f492237b2 100644
--- a/src/com/android/bluetooth/gatt/ContextMap.java
+++ b/src/com/android/bluetooth/gatt/ContextMap.java
@@ -27,6 +27,8 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
+import java.util.HashMap;
+import java.util.Map;
/**
* Helper class that keeps track of registered GATT applications.
@@ -306,6 +308,17 @@ import java.util.UUID;
}
/**
+ * Returns connect device map with addr and appid
+ */
+ Map<Integer, String> getConnectedMap(){
+ Map<Integer, String> connectedmap = new HashMap<Integer, String>();
+ for(Connection conn: mConnections){
+ connectedmap.put(conn.appId, conn.address);
+ }
+ return connectedmap;
+ }
+
+ /**
* Logs debug information.
*/
void dump(StringBuilder sb) {
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index fbeaad3ab..04c9da5b0 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -546,6 +546,20 @@ public class GattService extends ProfileService {
if (service == null) return;
service.stopMultiAdvertising(new AdvertiseClient(clientIf));
}
+
+ @Override
+ public void disconnectAll() {
+ GattService service = getService();
+ if (service == null) return;
+ service.disconnectAll();
+ }
+
+ @Override
+ public void unregAll() {
+ GattService service = getService();
+ if (service == null) return;
+ service.unregAll();
+ }
};
/**************************************************************************
@@ -1333,6 +1347,23 @@ public class GattService extends ProfileService {
mScanManager.stopScan(client);
}
+ void disconnectAll() {
+ if (DBG) Log.d(TAG, "disconnectAll()");
+ Map<Integer, String> connMap = mClientMap.getConnectedMap();
+ for(Map.Entry<Integer, String> entry:connMap.entrySet()){
+ if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue());
+ clientDisconnect(entry.getKey(), entry.getValue());
+ //clientDisconnect(int clientIf, String address)
+ }
+ }
+
+ void unregAll() {
+ for(ClientMap.App app:mClientMap.mApps){
+ if (DBG) Log.d(TAG, "unreg:" + app.id);
+ unregisterClient(app.id);
+ }
+ }
+
/**************************************************************************
* GATT Service functions - CLIENT
*************************************************************************/
diff --git a/src/com/android/bluetooth/hid/HidService.java b/src/com/android/bluetooth/hid/HidService.java
index 418c13b7d..be769fc80 100755
--- a/src/com/android/bluetooth/hid/HidService.java
+++ b/src/com/android/bluetooth/hid/HidService.java
@@ -47,7 +47,7 @@ import java.util.Map;
* @hide
*/
public class HidService extends ProfileService {
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String TAG = "HidService";
private Map<BluetoothDevice, Integer> mInputDevices;