summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jni/com_android_bluetooth_gatt.cpp4
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java25
-rw-r--r--src/com/android/bluetooth/gatt/AdvertiseManager.java102
-rw-r--r--src/com/android/bluetooth/gatt/GattService.java11
4 files changed, 105 insertions, 37 deletions
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index 921ad83b3..b85b9e911 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -1715,6 +1715,8 @@ static JNINativeMethod sAdvertiseMethods[] = {
{"gattClientUpdateAdvNative", "(IIIIIII)V", (void *) gattClientUpdateAdvNative},
{"gattClientSetAdvDataNative", "(IZZZI[B[B[B)V", (void *) gattClientSetAdvDataNative},
{"gattClientDisableAdvNative", "(I)V", (void *) gattClientDisableAdvNative},
+ {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative},
+ {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative},
};
// JNI functions defined in ScanManager class.
@@ -1758,7 +1760,6 @@ static JNINativeMethod sMethods[] = {
{"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative},
{"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative},
{"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative},
- {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative},
{"gattClientConfigureMTUNative", "(II)V", (void *) gattClientConfigureMTUNative},
{"gattConnectionParameterUpdateNative", "(ILjava/lang/String;IIII)V", (void *) gattConnectionParameterUpdateNative},
{"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative},
@@ -1776,7 +1777,6 @@ static JNINativeMethod sMethods[] = {
{"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative},
{"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative},
- {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative},
{"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative},
};
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 13416b391..9141d3eb8 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -54,14 +54,16 @@ import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.util.Pair;
+
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.hid.HidService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hdp.HealthService;
import com.android.bluetooth.pan.PanService;
-import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
+import com.android.internal.R;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
@@ -71,6 +73,7 @@ import java.util.Map;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.List;
+
import android.content.pm.PackageManager;
import android.os.ServiceManager;
@@ -547,7 +550,7 @@ public class AdapterService extends Service {
String serviceName = services[i].getName();
Integer serviceState = mProfileServicesState.get(serviceName);
if(serviceState != null && serviceState != expectedCurrentState) {
- debugLog("setProfileServiceState() - Unable to "
+ debugLog("setProfileServiceState() - Unable to "
+ (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
+ " service " + serviceName
+ ". Invalid state: " + serviceState);
@@ -1071,8 +1074,13 @@ public class AdapterService extends Service {
public boolean isMultiAdvertisementSupported() {
AdapterService service = getService();
if (service == null) return false;
- int val = service.getNumOfAdvertisementInstancesSupported();
- return (val >= MIN_ADVT_INSTANCES_FOR_MA);
+ return service.isMultiAdvertisementSupported();
+ }
+
+ public boolean isPeripheralModeSupported() {
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.isPeripheralModeSupported();
}
public boolean isOffloadedFilteringSupported() {
@@ -1632,6 +1640,11 @@ public class AdapterService extends Service {
return mAdapterProperties.getNumOfAdvertisementInstancesSupported();
}
+ public boolean isMultiAdvertisementSupported() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA;
+ }
+
public boolean isRpaOffloadSupported() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mAdapterProperties.isRpaOffloadSupported();
@@ -1647,6 +1660,10 @@ public class AdapterService extends Service {
return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
}
+ public boolean isPeripheralModeSupported() {
+ return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported);
+ }
+
public int getOffloadedScanResultStorage() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mAdapterProperties.getOffloadedScanResultStorage();
diff --git a/src/com/android/bluetooth/gatt/AdvertiseManager.java b/src/com/android/bluetooth/gatt/AdvertiseManager.java
index a2c859316..91932bb10 100644
--- a/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -40,7 +40,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
- * Manages Bluetooth LE advertising operations and interacts with bluedroid stack.
+ * Manages Bluetooth LE advertising operations and interacts with bluedroid stack. TODO: add tests.
*
* @hide
*/
@@ -56,6 +56,7 @@ class AdvertiseManager {
private static final int MSG_STOP_ADVERTISING = 1;
private final GattService mService;
+ private final AdapterService mAdapterService;
private final Set<AdvertiseClient> mAdvertiseClients;
private final AdvertiseNative mAdvertiseNative;
@@ -68,9 +69,10 @@ class AdvertiseManager {
/**
* Constructor of {@link AdvertiseManager}.
*/
- AdvertiseManager(GattService service) {
- mService = service;
+ AdvertiseManager(GattService service, AdapterService adapterService) {
logd("advertise manager created");
+ mService = service;
+ mAdapterService = adapterService;
mAdvertiseClients = new HashSet<AdvertiseClient>();
mAdvertiseNative = new AdvertiseNative();
}
@@ -218,13 +220,17 @@ class AdvertiseManager {
}
// Returns maximum advertise instances supported by controller.
- private int maxAdvertiseInstances() {
- AdapterService adapter = AdapterService.getAdapterService();
- int numOfAdvtInstances = adapter.getNumOfAdvertisementInstancesSupported();
+ int maxAdvertiseInstances() {
// Note numOfAdvtInstances includes the standard advertising instance.
// TODO: remove - 1 once the stack is able to include standard instance for multiple
// advertising.
- return numOfAdvtInstances - 1;
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ return mAdapterService.getNumOfAdvertisementInstancesSupported() - 1;
+ }
+ if (mAdapterService.isPeripheralModeSupported()) {
+ return 1;
+ }
+ return 0;
}
}
@@ -258,21 +264,33 @@ class AdvertiseManager {
private static final int ADVERTISING_EVENT_TYPE_SCANNABLE = 2;
private static final int ADVERTISING_EVENT_TYPE_NON_CONNECTABLE = 3;
+ // TODO: Extract advertising logic into interface as we have multiple implementations now.
boolean startAdverising(AdvertiseClient client) {
- int clientIf = client.clientIf;
+ if (!mAdapterService.isMultiAdvertisementSupported() &&
+ !mAdapterService.isPeripheralModeSupported()) {
+ return false;
+ }
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ return startMultiAdvertising(client);
+ }
+ return startSingleAdvertising(client);
+ }
+
+ boolean startMultiAdvertising(AdvertiseClient client) {
+ logd("starting multi advertising");
resetCountDownLatch();
- mAdvertiseNative.enableAdvertising(client);
+ enableAdvertising(client);
if (!waitForCallback()) {
return false;
}
resetCountDownLatch();
- mAdvertiseNative.setAdvertisingData(clientIf, client.advertiseData, false);
+ setAdvertisingData(client, client.advertiseData, false);
if (!waitForCallback()) {
return false;
}
if (client.scanResponse != null) {
resetCountDownLatch();
- mAdvertiseNative.setAdvertisingData(clientIf, client.scanResponse, true);
+ setAdvertisingData(client, client.scanResponse, true);
if (!waitForCallback()) {
return false;
}
@@ -280,8 +298,29 @@ class AdvertiseManager {
return true;
}
+ boolean startSingleAdvertising(AdvertiseClient client) {
+ logd("starting single advertising");
+ resetCountDownLatch();
+ enableAdvertising(client);
+ if (!waitForCallback()) {
+ return false;
+ }
+ setAdvertisingData(client, client.advertiseData, false);
+ return true;
+ }
+
void stopAdvertising(AdvertiseClient client) {
- gattClientDisableAdvNative(client.clientIf);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientDisableAdvNative(client.clientIf);
+ } else {
+ gattAdvertiseNative(client.clientIf, false);
+ try {
+ mService.onAdvertiseInstanceDisabled(
+ AdvertiseCallback.ADVERTISE_SUCCESS, client.clientIf);
+ } catch (RemoteException e) {
+ Log.d(TAG, "failed onAdvertiseInstanceDisabled", e);
+ }
+ }
}
private void resetCountDownLatch() {
@@ -305,16 +344,21 @@ class AdvertiseManager {
int txPowerLevel = getTxPowerLevel(client.settings);
int advertiseTimeoutSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(
client.settings.getTimeout());
- gattClientEnableAdvNative(
- clientIf,
- minAdvertiseUnit, maxAdvertiseUnit,
- advertiseEventType,
- ADVERTISING_CHANNEL_ALL,
- txPowerLevel,
- advertiseTimeoutSeconds);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientEnableAdvNative(
+ clientIf,
+ minAdvertiseUnit, maxAdvertiseUnit,
+ advertiseEventType,
+ ADVERTISING_CHANNEL_ALL,
+ txPowerLevel,
+ advertiseTimeoutSeconds);
+ } else {
+ gattAdvertiseNative(client.clientIf, true);
+ }
}
- private void setAdvertisingData(int clientIf, AdvertiseData data, boolean isScanResponse) {
+ private void setAdvertisingData(AdvertiseClient client, AdvertiseData data,
+ boolean isScanResponse) {
if (data == null) {
return;
}
@@ -340,9 +384,15 @@ class AdvertiseManager {
}
serviceUuids = advertisingUuidBytes.array();
}
- gattClientSetAdvDataNative(clientIf, isScanResponse, includeName, includeTxPower,
- appearance,
- manufacturerData, serviceData, serviceUuids);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+ includeTxPower, appearance,
+ manufacturerData, serviceData, serviceUuids);
+ } else {
+ gattSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+ includeTxPower, 0, 0, appearance,
+ manufacturerData, serviceData, serviceUuids);
+ }
}
// Combine manufacturer id and manufacturer data.
@@ -441,6 +491,12 @@ class AdvertiseManager {
private native void gattClientSetAdvDataNative(int client_if,
boolean set_scan_rsp, boolean incl_name, boolean incl_txpower, int appearance,
byte[] manufacturer_data, byte[] service_data, byte[] service_uuid);
+
+ private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName,
+ boolean inclTxPower, int minSlaveConnectionInterval, int maxSlaveConnectionInterval,
+ int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid);
+
+ private native void gattAdvertiseNative(int client_if, boolean start);
}
private void logd(String s) {
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 982fd16e7..108e22ae4 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -40,6 +40,7 @@ import android.os.SystemClock;
import android.util.Log;
import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import java.util.ArrayList;
@@ -160,7 +161,7 @@ public class GattService extends ProfileService {
protected boolean start() {
if (DBG) Log.d(TAG, "start()");
initializeNative();
- mAdvertiseManager = new AdvertiseManager(this);
+ mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService());
mAdvertiseManager.start();
mScanManager = new ScanManager(this);
@@ -546,7 +547,6 @@ public class GattService extends ProfileService {
void onScanResult(String address, int rssi, byte[] adv_data) {
if (VDBG) Log.d(TAG, "onScanResult() - address=" + address
+ ", rssi=" + rssi);
- ScanRecord record = ScanRecord.parseFromBytes(adv_data);
List<UUID> remoteUuids = parseUuids(adv_data);
for (ScanClient client : mScanManager.getRegularScanQueue()) {
if (client.uuids.length > 0) {
@@ -1175,6 +1175,7 @@ public class GattService extends ProfileService {
// Callback for standard advertising instance.
void onAdvertiseCallback(int status, int clientIf) {
if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status);
+ mAdvertiseManager.callbackDone(clientIf, status);
}
// Followings are callbacks for Bluetooth LE Advertise operations.
@@ -2274,17 +2275,11 @@ public class GattService extends ProfileService {
private native void gattClientReadRemoteRssiNative(int clientIf,
String address);
- private native void gattAdvertiseNative(int client_if, boolean start);
-
private native void gattClientConfigureMTUNative(int conn_id, int mtu);
private native void gattConnectionParameterUpdateNative(int client_if, String address,
int minInterval, int maxInterval, int latency, int timeout);
- private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName,
- boolean inclTxPower, int minInterval, int maxInterval,
- int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid);
-
private native void gattServerRegisterAppNative(long app_uuid_lsb,
long app_uuid_msb);