Merge "Bluetooth 5 AdvertisingSet implementation (2/4)"
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index 91e026c..08da8e0 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -118,6 +118,14 @@
return env->NewStringUTF(c_address);
}
+static std::vector<uint8_t> toVector(JNIEnv* env, jbyteArray ba) {
+ jbyte* data_data = env->GetByteArrayElements(ba, NULL);
+ uint16_t data_len = (uint16_t)env->GetArrayLength(ba);
+ std::vector<uint8_t> data_vec(data_data, data_data + data_len);
+ env->ReleaseByteArrayElements(ba, data_data, JNI_ABORT);
+ return data_vec;
+}
+
namespace android {
/**
@@ -176,7 +184,13 @@
* Advertiser callback methods
*/
static jmethodID method_onAdvertisingSetStarted;
-static jmethodID method_onAdvertisingSetEnabled;
+static jmethodID method_onAdvertisingEnabled;
+static jmethodID method_onAdvertisingDataSet;
+static jmethodID method_onScanResponseDataSet;
+static jmethodID method_onAdvertisingParametersUpdated;
+static jmethodID method_onPeriodicAdvertisingParametersUpdated;
+static jmethodID method_onPeriodicAdvertisingDataSet;
+static jmethodID method_onPeriodicAdvertisingEnable;
/**
* Static variables
@@ -1545,9 +1559,21 @@
static void advertiseClassInitNative(JNIEnv* env, jclass clazz) {
method_onAdvertisingSetStarted =
- env->GetMethodID(clazz, "onAdvertisingSetStarted", "(III)V");
- method_onAdvertisingSetEnabled =
- env->GetMethodID(clazz, "onAdvertisingSetEnabled", "(IZI)V");
+ env->GetMethodID(clazz, "onAdvertisingSetStarted", "(IIII)V");
+ method_onAdvertisingEnabled =
+ env->GetMethodID(clazz, "onAdvertisingEnabled", "(IZI)V");
+ method_onAdvertisingDataSet =
+ env->GetMethodID(clazz, "onAdvertisingDataSet", "(II)V");
+ method_onScanResponseDataSet =
+ env->GetMethodID(clazz, "onScanResponseDataSet", "(II)V");
+ method_onAdvertisingParametersUpdated =
+ env->GetMethodID(clazz, "onAdvertisingParametersUpdated", "(III)V");
+ method_onPeriodicAdvertisingParametersUpdated = env->GetMethodID(
+ clazz, "onPeriodicAdvertisingParametersUpdated", "(II)V");
+ method_onPeriodicAdvertisingDataSet =
+ env->GetMethodID(clazz, "onPeriodicAdvertisingDataSet", "(II)V");
+ method_onPeriodicAdvertisingEnable =
+ env->GetMethodID(clazz, "onPeriodicAdvertisingEnable", "(IZI)V");
}
static void advertiseInitializeNative(JNIEnv* env, jobject object) {
@@ -1638,12 +1664,12 @@
}
static void ble_advertising_set_started_cb(int reg_id, uint8_t advertiser_id,
- uint8_t status) {
+ int8_t tx_power, uint8_t status) {
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
sCallbackEnv->CallVoidMethod(mAdvertiseCallbacksObj,
method_onAdvertisingSetStarted, reg_id,
- advertiser_id, status);
+ advertiser_id, tx_power, status);
}
static void ble_advertising_set_timeout_cb(uint8_t advertiser_id,
@@ -1651,7 +1677,7 @@
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
sCallbackEnv->CallVoidMethod(mAdvertiseCallbacksObj,
- method_onAdvertisingSetEnabled, advertiser_id,
+ method_onAdvertisingEnabled, advertiser_id,
false, status);
}
@@ -1700,6 +1726,116 @@
sGattIf->advertiser->Unregister(advertiser_id);
}
+static void callJniCallback(jmethodID method, uint8_t advertiser_id,
+ uint8_t status) {
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+ sCallbackEnv->CallVoidMethod(mAdvertiseCallbacksObj, method, advertiser_id,
+ status);
+}
+
+static void enableSetCb(uint8_t advertiser_id, bool enable, uint8_t status) {
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+ sCallbackEnv->CallVoidMethod(mAdvertiseCallbacksObj,
+ method_onAdvertisingEnabled, advertiser_id,
+ enable, status);
+}
+
+static void enableAdvertisingSetNative(JNIEnv* env, jobject object,
+ jint advertiser_id, jboolean enable,
+ jint timeout) {
+ if (!sGattIf) return;
+
+ sGattIf->advertiser->Enable(
+ advertiser_id, enable, base::Bind(&enableSetCb, advertiser_id, enable),
+ timeout / 1000, base::Bind(&enableSetCb, advertiser_id, false));
+}
+
+static void setAdvertisingDataNative(JNIEnv* env, jobject object,
+ jint advertiser_id, jbyteArray data) {
+ if (!sGattIf) return;
+
+ sGattIf->advertiser->SetData(
+ advertiser_id, false, toVector(env, data),
+ base::Bind(&callJniCallback, method_onAdvertisingDataSet, advertiser_id));
+}
+
+static void setScanResponseDataNative(JNIEnv* env, jobject object,
+ jint advertiser_id, jbyteArray data) {
+ if (!sGattIf) return;
+
+ sGattIf->advertiser->SetData(
+ advertiser_id, true, toVector(env, data),
+ base::Bind(&callJniCallback, method_onScanResponseDataSet,
+ advertiser_id));
+}
+
+static void setAdvertisingParametersNativeCb(uint8_t advertiser_id,
+ uint8_t status, int8_t tx_power) {
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+ sCallbackEnv->CallVoidMethod(mCallbacksObj,
+ method_onAdvertisingParametersUpdated,
+ advertiser_id, tx_power, status);
+}
+
+static void setAdvertisingParametersNative(JNIEnv* env, jobject object,
+ jint advertiser_id,
+ jobject parameters) {
+ if (!sGattIf) return;
+
+ // TODO: must learn somehow wether scan response is set ?
+ AdvertiseParameters params =
+ parseParams(env, parameters, false /*TODO: put proper value here!!!*/);
+ sGattIf->advertiser->SetParameters(
+ advertiser_id, params,
+ base::Bind(setAdvertisingParametersNativeCb, advertiser_id));
+}
+
+static void setPeriodicAdvertisingParametersNative(
+ JNIEnv* env, jobject object, jint advertiser_id,
+ jobject periodic_parameters) {
+ if (!sGattIf) return;
+
+ PeriodicAdvertisingParameters periodicParams =
+ parsePeriodicParams(env, periodic_parameters);
+ sGattIf->advertiser->SetPeriodicAdvertisingParameters(
+ advertiser_id, periodicParams,
+ base::Bind(&callJniCallback,
+ method_onPeriodicAdvertisingParametersUpdated, advertiser_id));
+}
+
+static void setPeriodicAdvertisingDataNative(JNIEnv* env, jobject object,
+ jint advertiser_id,
+ jbyteArray data) {
+ if (!sGattIf) return;
+
+ sGattIf->advertiser->SetPeriodicAdvertisingData(
+ advertiser_id, toVector(env, data),
+ base::Bind(&callJniCallback, method_onPeriodicAdvertisingDataSet,
+ advertiser_id));
+}
+
+static void enablePeriodicSetCb(uint8_t advertiser_id, bool enable,
+ uint8_t status) {
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+ sCallbackEnv->CallVoidMethod(mCallbacksObj,
+ method_onPeriodicAdvertisingEnable,
+ advertiser_id, enable, status);
+}
+
+static void setPeriodicAdvertisingEnableNative(JNIEnv* env, jobject object,
+ jint advertiser_id,
+ jboolean enable) {
+ if (!sGattIf) return;
+
+ sGattIf->advertiser->SetPeriodicAdvertisingEnable(
+ advertiser_id, enable,
+ base::Bind(&enablePeriodicSetCb, advertiser_id, enable));
+}
+
static void gattTestNative(JNIEnv* env, jobject object, jint command,
jlong uuid1_lsb, jlong uuid1_msb, jstring bda1,
jint p1, jint p2, jint p3, jint p4, jint p5) {
@@ -1736,6 +1872,19 @@
"le/PeriodicAdvertisingParameters;[BII)V",
(void*)startAdvertisingSetNative},
{"stopAdvertisingSetNative", "(I)V", (void*)stopAdvertisingSetNative},
+ {"enableAdvertisingSetNative", "(IZI)V", (void*)enableAdvertisingSetNative},
+ {"setAdvertisingDataNative", "(I[B)V", (void*)setAdvertisingDataNative},
+ {"setScanResponseDataNative", "(I[B)V", (void*)setScanResponseDataNative},
+ {"setAdvertisingParametersNative",
+ "(ILandroid/bluetooth/le/AdvertisingSetParameters;)V",
+ (void*)setAdvertisingParametersNative},
+ {"setPeriodicAdvertisingParametersNative",
+ "(ILandroid/bluetooth/le/PeriodicAdvertisingParameters;)V",
+ (void*)setPeriodicAdvertisingParametersNative},
+ {"setPeriodicAdvertisingDataNative", "(I[B)V",
+ (void*)setPeriodicAdvertisingDataNative},
+ {"setPeriodicAdvertisingEnableNative", "(IZ)V",
+ (void*)setPeriodicAdvertisingEnableNative},
};
// JNI functions defined in ScanManager class.
diff --git a/src/com/android/bluetooth/gatt/AdvertiseManager.java b/src/com/android/bluetooth/gatt/AdvertiseManager.java
index 19c939f..2b981ec 100644
--- a/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -134,7 +134,8 @@
return entry;
}
- void onAdvertisingSetStarted(int reg_id, int advertiser_id, int status) throws Exception {
+ void onAdvertisingSetStarted(int reg_id, int advertiser_id, int tx_power, int status)
+ throws Exception {
if (DBG)
Log.d(TAG, "onAdvertisingSetStarted() - reg_id=" + reg_id + ", advertiser_id="
+ advertiser_id + ", status=" + status);
@@ -158,10 +159,10 @@
mAdvertisers.remove(binder);
}
- callback.onAdvertisingSetStarted(advertiser_id, status);
+ callback.onAdvertisingSetStarted(advertiser_id, tx_power, status);
}
- void onAdvertisingSetEnabled(int advertiser_id, boolean enable, int status) throws Exception {
+ void onAdvertisingEnabled(int advertiser_id, boolean enable, int status) throws Exception {
logd("onAdvertisingSetEnabled() - advertiser_id=" + advertiser_id + ", enable=" + enable
+ ", status=" + status);
@@ -222,6 +223,125 @@
stopAdvertisingSetNative(advertiser_id);
}
+ void enableAdvertisingSet(int advertiserId, boolean enable, int timeout) {
+ enableAdvertisingSetNative(advertiserId, enable, timeout);
+ }
+
+ void setAdvertisingData(int advertiserId, AdvertiseData data) {
+ String deviceName = AdapterService.getAdapterService().getName();
+ setAdvertisingDataNative(
+ advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ }
+
+ void setScanResponseData(int advertiserId, AdvertiseData data) {
+ String deviceName = AdapterService.getAdapterService().getName();
+ setScanResponseDataNative(
+ advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ }
+
+ void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
+ setAdvertisingParametersNative(advertiserId, parameters);
+ }
+
+ void setPeriodicAdvertisingParameters(
+ int advertiserId, PeriodicAdvertisingParameters parameters) {
+ setPeriodicAdvertisingParametersNative(advertiserId, parameters);
+ }
+
+ void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
+ String deviceName = AdapterService.getAdapterService().getName();
+ setPeriodicAdvertisingDataNative(
+ advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ }
+
+ void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
+ setPeriodicAdvertisingEnableNative(advertiserId, enable);
+ }
+
+ void onAdvertisingDataSet(int advertiser_id, int status) throws Exception {
+ logd("onAdvertisingDataSet() advertiser_id=" + advertiser_id + ", status=" + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onAdvertisingDataSet() - bad advertiser_id " + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onAdvertisingDataSet(advertiser_id, status);
+ }
+
+ void onScanResponseDataSet(int advertiser_id, int status) throws Exception {
+ logd("onScanResponseDataSet() advertiser_id=" + advertiser_id + ", status=" + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onScanResponseDataSet() - bad advertiser_id " + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onScanResponseDataSet(advertiser_id, status);
+ }
+
+ void onAdvertisingParametersUpdated(int advertiser_id, int tx_power, int status)
+ throws Exception {
+ logd("onAdvertisingParametersUpdated() advertiser_id=" + advertiser_id + ", tx_power="
+ + tx_power + ", status=" + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onAdvertisingParametersUpdated() - bad advertiser_id " + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onAdvertisingParametersUpdated(advertiser_id, tx_power, status);
+ }
+
+ void onPeriodicAdvertisingParametersUpdated(int advertiser_id, int status) throws Exception {
+ logd("onPeriodicAdvertisingParametersUpdated() advertiser_id=" + advertiser_id + ", status="
+ + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onPeriodicAdvertisingParametersUpdated() - bad advertiser_id "
+ + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onPeriodicAdvertisingParametersUpdated(advertiser_id, status);
+ }
+
+ void onPeriodicAdvertisingDataSet(int advertiser_id, int status) throws Exception {
+ logd("onPeriodicAdvertisingDataSet() advertiser_id=" + advertiser_id + ", status="
+ + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onPeriodicAdvertisingDataSet() - bad advertiser_id " + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onPeriodicAdvertisingDataSet(advertiser_id, status);
+ }
+
+ void onPeriodicAdvertisingEnable(int advertiser_id, boolean enable, int status)
+ throws Exception {
+ logd("onPeriodicAdvertisingEnable() advertiser_id=" + advertiser_id + ", status=" + status);
+
+ Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiser_id);
+ if (entry == null) {
+ Log.i(TAG, "onAdvertisingSetEnable() - bad advertiser_id " + advertiser_id);
+ return;
+ }
+
+ IAdvertisingSetCallback callback = entry.getValue().callback;
+ callback.onPeriodicAdvertisingEnable(advertiser_id, enable, status);
+ }
+
private void logd(String s) {
if (DBG) {
Log.d(TAG, s);
@@ -239,6 +359,14 @@
byte[] advertiseData, byte[] scanResponse,
PeriodicAdvertisingParameters periodicParameters, byte[] periodicData, int timeout,
int reg_id);
-
private native void stopAdvertisingSetNative(int advertiser_id);
+ private native void enableAdvertisingSetNative(int advertiserId, boolean enable, int timeout);
+ private native void setAdvertisingDataNative(int advertiserId, byte[] data);
+ private native void setScanResponseDataNative(int advertiserId, byte[] data);
+ private native void setAdvertisingParametersNative(
+ int advertiserId, AdvertisingSetParameters parameters);
+ private native void setPeriodicAdvertisingParametersNative(
+ int advertiserId, PeriodicAdvertisingParameters parameters);
+ private native void setPeriodicAdvertisingDataNative(int advertiserId, byte[] data);
+ private native void setPeriodicAdvertisingEnableNative(int advertiserId, boolean enable);
}
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 3ca5363..03cf7ed 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -559,48 +559,48 @@
service.stopAdvertisingSet(callback);
}
- public void enableAdverisingSet(int advertiserId, boolean enable, int timeout) {
+ public void enableAdvertisingSet(int advertiserId, boolean enable, int timeout) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.enableAdvertisingSet(advertiserId, enable, timeout);
}
public void setAdvertisingData(int advertiserId, AdvertiseData data) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setAdvertisingData(advertiserId, data);
}
public void setScanResponseData(int advertiserId, AdvertiseData data) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setScanResponseData(advertiserId, data);
}
public void setAdvertisingParameters(
int advertiserId, AdvertisingSetParameters parameters) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setAdvertisingParameters(advertiserId, parameters);
}
public void setPeriodicAdvertisingParameters(
int advertiserId, PeriodicAdvertisingParameters parameters) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setPeriodicAdvertisingParameters(advertiserId, parameters);
}
public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setPeriodicAdvertisingData(advertiserId, data);
}
- public void periodicAdvertisingEnable(int advertiserId, boolean enable) {
+ public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
GattService service = getService();
if (service == null) return;
- // TODO: implement
+ service.setPeriodicAdvertisingEnable(advertiserId, enable);
}
@Override
@@ -1423,17 +1423,51 @@
AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData, int timeout, IAdvertisingSetCallback callback) {
enforceAdminPermission();
-
mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse,
periodicParameters, periodicData, timeout, callback);
}
void stopAdvertisingSet(IAdvertisingSetCallback callback) {
enforceAdminPermission();
-
mAdvertiseManager.stopAdvertisingSet(callback);
}
+ void enableAdvertisingSet(int advertiserId, boolean enable, int timeout) {
+ enforceAdminPermission();
+ mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, timeout);
+ }
+
+ void setAdvertisingData(int advertiserId, AdvertiseData data) {
+ enforceAdminPermission();
+ mAdvertiseManager.setAdvertisingData(advertiserId, data);
+ }
+
+ void setScanResponseData(int advertiserId, AdvertiseData data) {
+ enforceAdminPermission();
+ mAdvertiseManager.setScanResponseData(advertiserId, data);
+ }
+
+ void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
+ enforceAdminPermission();
+ mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters);
+ }
+
+ void setPeriodicAdvertisingParameters(
+ int advertiserId, PeriodicAdvertisingParameters parameters) {
+ enforceAdminPermission();
+ mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters);
+ }
+
+ void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
+ enforceAdminPermission();
+ mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data);
+ }
+
+ void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
+ enforceAdminPermission();
+ mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable);
+ }
+
/**************************************************************************
* GATT Service functions - CLIENT
*************************************************************************/