DO NOT MERGE: Add status callback for start/stop advertising.
cherrypick from master to fix b/13289050

Change-Id: I666969442b756ce461ff64eff0d09f5283431fb3
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index d2cfd84..1ffac4e 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -158,6 +158,7 @@
 static jmethodID method_onGetIncludedService;
 static jmethodID method_onRegisterForNotifications;
 static jmethodID method_onReadRemoteRssi;
+static jmethodID method_onAdvertiseCallback;
 
 /**
  * Server callback methods
@@ -422,6 +423,13 @@
     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,
@@ -439,7 +447,8 @@
     btgattc_read_descriptor_cb,
     btgattc_write_descriptor_cb,
     btgattc_execute_write_cb,
-    btgattc_remote_rssi_cb
+    btgattc_remote_rssi_cb,
+    btgattc_advertise_cb
 };
 
 
@@ -670,6 +679,7 @@
     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!");
 }
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 0091ef5..71000a5 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -17,6 +17,7 @@
 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;
@@ -103,7 +104,9 @@
     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
      */
@@ -226,7 +229,7 @@
         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);
             }
@@ -917,6 +920,54 @@
         }
     }
 
+    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
      *************************************************************************/
@@ -1118,7 +1169,7 @@
 
     boolean isAdvertising() {
         enforcePrivilegedPermission();
-        return mIsAdvertising;
+        return mAdvertisingState != BluetoothAdapter.STATE_ADVERTISE_STOPPED;
     }
 
     void startAdvertising(int clientIf) {
@@ -1154,15 +1205,24 @@
         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() {