static jmethodID method_onGetIncludedService;
static jmethodID method_onRegisterForNotifications;
static jmethodID method_onReadRemoteRssi;
+static jmethodID method_onAdvertiseCallback;
/**
* Server callback methods
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
+void btgattc_advertise_cb(int status, int client_if)
+{
+ CHECK_CALLBACK_ENV
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiseCallback, status, client_if);
+ checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
static const btgatt_client_callbacks_t sGattClientCallbacks = {
btgattc_register_app_cb,
btgattc_scan_result_cb,
btgattc_read_descriptor_cb,
btgattc_write_descriptor_cb,
btgattc_execute_write_cb,
- btgattc_remote_rssi_cb
+ btgattc_remote_rssi_cb,
+ btgattc_advertise_cb
};
method_onAttributeRead= env->GetMethodID(clazz, "onAttributeRead", "(Ljava/lang/String;IIIIZ)V");
method_onAttributeWrite= env->GetMethodID(clazz, "onAttributeWrite", "(Ljava/lang/String;IIIIIZZ[B)V");
method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V");
+ method_onAdvertiseCallback = env->GetMethodID(clazz, "onAdvertiseCallback", "(II)V");
info("classInitNative: Success!");
}
package com.android.bluetooth.gatt;
import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
private byte[] mServiceData = new byte[0];
private int mManufacturerCode = -1;
private byte[] mManufacturerData = new byte[0];
- private boolean mIsAdvertising = false;
+ private Integer mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED;
+ private final Object mLock = new Object();
+
/**
* Pending service declaration queue
*/
public void binderDied() {
if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!");
if (mAdvertisingClientIf == mAppIf) {
- stopAdvertising();
+ stopAdvertising(true); // force stop advertising.
} else {
stopScan(mAppIf, false);
}
}
}
+ void onAdvertiseCallback(int status, int clientIf) throws RemoteException {
+ if (DBG) Log.d(TAG, "onClientListen() status=" + status);
+ synchronized (mLock) {
+ if (DBG) Log.d(TAG, "state" + mAdvertisingState);
+ // Invalid advertising state
+ if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STARTED ||
+ mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STOPPED) {
+ Log.e(TAG, "invalid callback state " + mAdvertisingState);
+ return;
+ }
+
+ // Force stop advertising, no callback.
+ if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_FORCE_STOPPING) {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED;
+ mAdvertisingClientIf = 0;
+ sendBroadcast(new Intent(
+ BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STOPPED));
+ return;
+ }
+
+ if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STARTING) {
+ if (status == 0) {
+ mAdvertisingClientIf = clientIf;
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTED;
+ sendBroadcast(new Intent(
+ BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STARTED));
+ } else {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED;
+ }
+ } else if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STOPPING) {
+ if (status == 0) {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED;
+ sendBroadcast(new Intent(
+ BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STOPPED));
+ mAdvertisingClientIf = 0;
+ } else {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTED;
+ }
+ }
+ }
+ ClientMap.App app = mClientMap.getById(clientIf);
+ if (app == null || app.callback == null) {
+ Log.e(TAG, "app or callback is null");
+ return;
+ }
+ app.callback.onAdvertiseStateChange(mAdvertisingState, status);
+ }
+
/**************************************************************************
* GATT Service functions - Shared CLIENT/SERVER
*************************************************************************/
boolean isAdvertising() {
enforcePrivilegedPermission();
- return mIsAdvertising;
+ return mAdvertisingState != BluetoothAdapter.STATE_ADVERTISE_STOPPED;
}
void startAdvertising(int clientIf) {
if (!isAdvertising()) {
gattAdvertiseNative(clientIf, true);
mAdvertisingClientIf = clientIf;
- mIsAdvertising = true;
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTING;
}
}
void stopAdvertising() {
+ stopAdvertising(false);
+ }
+
+ void stopAdvertising(boolean forceStop) {
enforcePrivilegedPermission();
gattAdvertiseNative(mAdvertisingClientIf, false);
- mAdvertisingClientIf = 0;
- mIsAdvertising = false;
+ synchronized (mLock) {
+ if (forceStop) {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_FORCE_STOPPING;
+ } else {
+ mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPING;
+ }
+ }
}
List<String> getConnectedDevices() {