diff options
-rw-r--r-- | jni/com_android_bluetooth_gatt.cpp | 4 | ||||
-rw-r--r-- | src/com/android/bluetooth/btservice/AdapterService.java | 25 | ||||
-rw-r--r-- | src/com/android/bluetooth/gatt/AdvertiseManager.java | 102 | ||||
-rw-r--r-- | src/com/android/bluetooth/gatt/GattService.java | 11 |
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); |