OSDN Git Service

Separate advertiser from GATT client (2/4)
authorJakub Pawlowski <jpawlowski@google.com>
Wed, 13 Jul 2016 18:56:59 +0000 (11:56 -0700)
committerJakub Pawlowski <jpawlowski@google.com>
Wed, 31 Aug 2016 10:26:44 +0000 (03:26 -0700)
Bug: 30622771
Change-Id: Icacf1fa6a526d67ffadb8acc056d2acfefc5e895

jni/com_android_bluetooth_gatt.cpp
src/com/android/bluetooth/gatt/AdvertiseClient.java
src/com/android/bluetooth/gatt/AdvertiseManager.java
src/com/android/bluetooth/gatt/GattService.java

index 01cf8e2..7106a67 100644 (file)
@@ -157,6 +157,7 @@ static jmethodID method_onConfigureMTU;
 static jmethodID method_onScanFilterConfig;
 static jmethodID method_onScanFilterParamsConfigured;
 static jmethodID method_onScanFilterEnableDisabled;
+static jmethodID method_onAdvertiserRegistered;
 static jmethodID method_onMultiAdvEnable;
 static jmethodID method_onMultiAdvUpdate;
 static jmethodID method_onMultiAdvSetAdvData;
@@ -408,34 +409,6 @@ void btgattc_scan_filter_status_cb(int action, int client_if, int status)
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
-void btgattc_multiadv_enable_cb(int client_if, int status)
-{
-    CHECK_CALLBACK_ENV
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvEnable, status,client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
-}
-
-void btgattc_multiadv_update_cb(int client_if, int status)
-{
-    CHECK_CALLBACK_ENV
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvUpdate, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
-}
-
-void btgattc_multiadv_setadv_data_cb(int client_if, int status)
-{
-    CHECK_CALLBACK_ENV
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvSetAdvData, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
-}
-
-void btgattc_multiadv_disable_cb(int client_if, int status)
-{
-    CHECK_CALLBACK_ENV
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvDisable, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
-}
-
 void btgattc_congestion_cb(int conn_id, bool congested)
 {
     CHECK_CALLBACK_ENV
@@ -609,10 +582,6 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = {
     btgattc_scan_filter_cfg_cb,
     btgattc_scan_filter_param_cb,
     btgattc_scan_filter_status_cb,
-    btgattc_multiadv_enable_cb,
-    btgattc_multiadv_update_cb,
-    btgattc_multiadv_setadv_data_cb,
-    btgattc_multiadv_disable_cb,
     btgattc_congestion_cb,
     btgattc_batchscan_cfg_storage_cb,
     btgattc_batchscan_startstop_cb,
@@ -625,6 +594,52 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = {
     NULL  /* services_added_cb */
 };
 
+/**
+ * Advertiser callbacks
+ */
+void ble_advertiser_register_cb(int status, int advertiser_id, bt_uuid_t *uuid)
+{
+    CHECK_CALLBACK_ENV
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiserRegistered,
+                                 status, advertiser_id, UUID_PARAMS(uuid));
+    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
+void ble_advertiser_enable_cb(int advertiser_id, int status)
+{
+    CHECK_CALLBACK_ENV
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvEnable, status,advertiser_id);
+    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
+void ble_advertiser_update_cb(int advertiser_id, int status)
+{
+    CHECK_CALLBACK_ENV
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvUpdate, status, advertiser_id);
+    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
+void ble_advertiser_setadv_data_cb(int advertiser_id, int status)
+{
+    CHECK_CALLBACK_ENV
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvSetAdvData, status, advertiser_id);
+    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
+void ble_advertiser_disable_cb(int advertiser_id, int status)
+{
+    CHECK_CALLBACK_ENV
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvDisable, status, advertiser_id);
+    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
+static const ble_advertiser_callbacks_t sGattAdvertiserCallbacks = {
+    ble_advertiser_register_cb,
+    ble_advertiser_enable_cb,
+    ble_advertiser_update_cb,
+    ble_advertiser_setadv_data_cb,
+    ble_advertiser_disable_cb
+};
 
 /**
  * BTA server callbacks
@@ -810,7 +825,8 @@ static const btgatt_server_callbacks_t sGattServerCallbacks = {
 static const btgatt_callbacks_t sGattCallbacks = {
     sizeof(btgatt_callbacks_t),
     &sGattClientCallbacks,
-    &sGattServerCallbacks
+    &sGattServerCallbacks,
+    &sGattAdvertiserCallbacks,
 };
 
 /**
@@ -838,6 +854,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
     method_onScanFilterConfig = env->GetMethodID(clazz, "onScanFilterConfig", "(IIIII)V");
     method_onScanFilterParamsConfigured = env->GetMethodID(clazz, "onScanFilterParamsConfigured", "(IIII)V");
     method_onScanFilterEnableDisabled = env->GetMethodID(clazz, "onScanFilterEnableDisabled", "(III)V");
+    method_onAdvertiserRegistered = env->GetMethodID(clazz, "onAdvertiserRegistered", "(IIJJ)V");
     method_onMultiAdvEnable = env->GetMethodID(clazz, "onAdvertiseInstanceEnabled", "(II)V");
     method_onMultiAdvUpdate = env->GetMethodID(clazz, "onAdvertiseDataUpdated", "(II)V");
     method_onMultiAdvSetAdvData = env->GetMethodID(clazz, "onAdvertiseDataSet", "(II)V");
@@ -1128,7 +1145,7 @@ static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if,
     vector<uint8_t> service_uuid(arr_service_uuid, arr_service_uuid + arr_service_uuid_len);
     env->ReleaseByteArrayElements(serviceUuid, arr_service_uuid, JNI_ABORT);
 
-    sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower,
+    sGattIf->advertiser->set_adv_data(client_if, setScanRsp, inclName, inclTxPower,
         minInterval, maxInterval, appearance, std::move(data),
         std::move(service_data), std::move(service_uuid));
 }
@@ -1357,13 +1374,31 @@ static void gattConnectionParameterUpdateNative(JNIEnv *env, jobject object, jin
     sGattIf->client->conn_parameter_update(&bda, min_interval, max_interval, latency, timeout);
 }
 
+static void registerAdvertiserNative(JNIEnv* env, jobject object,
+                                     jlong app_uuid_lsb, jlong app_uuid_msb)
+{
+    bt_uuid_t uuid;
+
+    if (!sGattIf) return;
+
+    set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
+    sGattIf->advertiser->register_advertiser(&uuid);
+}
+
+static void unregisterAdvertiserNative(JNIEnv* env, jobject object, jint advertiser_id)
+{
+    if (!sGattIf) return;
+
+    sGattIf->advertiser->unregister_advertiser(advertiser_id);
+}
+
 static void gattClientEnableAdvNative(JNIEnv* env, jobject object, jint client_if,
        jint min_interval, jint max_interval, jint adv_type, jint chnl_map, jint tx_power,
        jint timeout_s)
 {
     if (!sGattIf) return;
 
-    sGattIf->client->multi_adv_enable(client_if, min_interval, max_interval, adv_type, chnl_map,
+    sGattIf->advertiser->multi_adv_enable(client_if, min_interval, max_interval, adv_type, chnl_map,
         tx_power, timeout_s);
 }
 
@@ -1373,7 +1408,7 @@ static void gattClientUpdateAdvNative(JNIEnv* env, jobject object, jint client_i
 {
     if (!sGattIf) return;
 
-    sGattIf->client->multi_adv_update(client_if, min_interval, max_interval, adv_type, chnl_map,
+    sGattIf->advertiser->multi_adv_update(client_if, min_interval, max_interval, adv_type, chnl_map,
         tx_power, timeout_s);
 }
 
@@ -1397,7 +1432,7 @@ static void gattClientSetAdvDataNative(JNIEnv* env, jobject object , jint client
     vector<uint8_t> serv_uuid_vec(serv_uuid, serv_uuid + serv_uuid_len);
     env->ReleaseByteArrayElements(service_uuid, serv_uuid, JNI_ABORT);
 
-    sGattIf->client->multi_adv_set_inst_data(client_if, set_scan_rsp, incl_name,incl_txpower,
+    sGattIf->advertiser->multi_adv_set_inst_data(client_if, set_scan_rsp, incl_name,incl_txpower,
                                              appearance, std::move(manu_vec),
                                              std::move(serv_data_vec), std::move(serv_uuid_vec));
 }
@@ -1405,7 +1440,7 @@ static void gattClientSetAdvDataNative(JNIEnv* env, jobject object , jint client
 static void gattClientDisableAdvNative(JNIEnv* env, jobject object, jint client_if)
 {
     if (!sGattIf) return;
-    sGattIf->client->multi_adv_disable(client_if);
+    sGattIf->advertiser->multi_adv_disable(client_if);
 }
 
 static void gattClientConfigBatchScanStorageNative(JNIEnv* env, jobject object, jint client_if,
@@ -1641,6 +1676,8 @@ static void gattTestNative(JNIEnv *env, jobject object, jint command,
 
 // JNI functions defined in AdvertiseManager class.
 static JNINativeMethod sAdvertiseMethods[] = {
+    {"registerAdvertiserNative", "(JJ)V", (void *) registerAdvertiserNative},
+    {"unregisterAdvertiserNative", "(I)V", (void *) unregisterAdvertiserNative},
     {"gattClientEnableAdvNative", "(IIIIIII)V", (void *) gattClientEnableAdvNative},
     {"gattClientUpdateAdvNative", "(IIIIIII)V", (void *) gattClientUpdateAdvNative},
     {"gattClientSetAdvDataNative", "(IZZZI[B[B[B)V", (void *) gattClientSetAdvDataNative},
index 34c7c86..22d8a1e 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Objects;
  * @hide
  */
 class AdvertiseClient {
-    int clientIf;
+    int advertiserId;
     // Associated application died.
     boolean appDied;
     AdvertiseSettings settings;
@@ -37,21 +37,21 @@ class AdvertiseClient {
     AdvertiseData scanResponse;
 
     /**
-     * @param clientIf - Identifier of the client.
+     * @param advertiserId - Identifier of the advertiser.
      */
-    AdvertiseClient(int clientIf) {
-        this.clientIf = clientIf;
+    AdvertiseClient(int advertiserId) {
+        this.advertiserId = advertiserId;
     }
 
     /**
-     * @param clientIf - Identifier of the client.
+     * @param advertiserId - Identifier of the advertiser.
      * @param settings - Settings for the advertising.
      * @param advertiseData - Advertise data broadcasted over the air.
      * @param scanResponse - Response of scan request, could be null.
      */
-    AdvertiseClient(int clientIf, AdvertiseSettings settings, AdvertiseData advertiseData,
+    AdvertiseClient(int advertiserId, AdvertiseSettings settings, AdvertiseData advertiseData,
             AdvertiseData scanResponse) {
-        this.clientIf = clientIf;
+        this.advertiserId = advertiserId;
         this.settings = settings;
         this.advertiseData = advertiseData;
         this.scanResponse = scanResponse;
@@ -66,11 +66,11 @@ class AdvertiseClient {
             return false;
         }
         AdvertiseClient other = (AdvertiseClient) obj;
-        return clientIf == other.clientIf;
+        return advertiserId == other.advertiserId;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(clientIf);
+        return Objects.hash(advertiserId);
     }
 }
index 3fb4aa9..6778d2b 100644 (file)
@@ -101,6 +101,15 @@ class AdvertiseManager {
         }
     }
 
+    void registerAdvertiser(UUID uuid) {
+        mAdvertiseNative.registerAdvertiserNative(
+            uuid.getLeastSignificantBits(), uuid.getMostSignificantBits());
+    }
+
+    void unregisterAdvertiser(int advertiserId) {
+        mAdvertiseNative.unregisterAdvertiserNative(advertiserId);
+    }
+
     /**
      * Start BLE advertising.
      *
@@ -132,34 +141,34 @@ class AdvertiseManager {
     /**
      * Signals the callback is received.
      *
-     * @param clientIf Identifier for the client.
+     * @param advertiserId Identifier for the client.
      * @param status Status of the callback.
      */
-    void callbackDone(int clientIf, int status) {
+    void callbackDone(int advertiserId, int status) {
         if (status == AdvertiseCallback.ADVERTISE_SUCCESS) {
             mLatch.countDown();
         } else {
             // Note in failure case we'll wait for the latch to timeout(which takes 100ms) and
             // the mClientHandler thread will be blocked till timeout.
-            postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+            postCallback(advertiserId, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
         }
     }
 
     // Post callback status to app process.
-    private void postCallback(int clientIf, int status) {
+    private void postCallback(int advertiserId, int status) {
         try {
-            AdvertiseClient client = getAdvertiseClient(clientIf);
+            AdvertiseClient client = getAdvertiseClient(advertiserId);
             AdvertiseSettings settings = (client == null) ? null : client.settings;
             boolean isStart = true;
-            mService.onMultipleAdvertiseCallback(clientIf, status, isStart, settings);
+            mService.onMultipleAdvertiseCallback(advertiserId, status, isStart, settings);
         } catch (RemoteException e) {
             loge("failed onMultipleAdvertiseCallback", e);
         }
     }
 
-    private AdvertiseClient getAdvertiseClient(int clientIf) {
+    private AdvertiseClient getAdvertiseClient(int advertiserId) {
         for (AdvertiseClient client : mAdvertiseClients) {
-            if (client.clientIf == clientIf) {
+            if (client.advertiserId == advertiserId) {
                 return client;
             }
         }
@@ -193,23 +202,24 @@ class AdvertiseManager {
 
         private void handleStartAdvertising(AdvertiseClient client) {
             Utils.enforceAdminPermission(mService);
-            int clientIf = client.clientIf;
+            int advertiserId = client.advertiserId;
             if (mAdvertiseClients.contains(client)) {
-                postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
+                postCallback(advertiserId, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
                 return;
             }
 
             if (mAdvertiseClients.size() >= maxAdvertiseInstances()) {
-                postCallback(clientIf,
+                postCallback(advertiserId,
                         AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS);
                 return;
             }
             if (!mAdvertiseNative.startAdverising(client)) {
-                postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+                postCallback(advertiserId, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
                 return;
             }
+
             mAdvertiseClients.add(client);
-            postCallback(clientIf, AdvertiseCallback.ADVERTISE_SUCCESS);
+            postCallback(advertiserId, AdvertiseCallback.ADVERTISE_SUCCESS);
         }
 
         // Handles stop advertising.
@@ -218,11 +228,11 @@ class AdvertiseManager {
             if (client == null) {
                 return;
             }
-            logd("stop advertise for client " + client.clientIf);
+            logd("stop advertise for client " + client.advertiserId);
             mAdvertiseNative.stopAdvertising(client);
             if (client.appDied) {
-                logd("app died - unregistering client : " + client.clientIf);
-                mService.unregisterClient(client.clientIf);
+                logd("app died - unregistering client : " + client.advertiserId);
+                mAdvertiseNative.unregisterAdvertiserNative(client.advertiserId);
             }
             if (mAdvertiseClients.contains(client)) {
                 mAdvertiseClients.remove(client);
@@ -321,12 +331,12 @@ class AdvertiseManager {
 
         void stopAdvertising(AdvertiseClient client) {
             if (mAdapterService.isMultiAdvertisementSupported()) {
-                gattClientDisableAdvNative(client.clientIf);
+                gattClientDisableAdvNative(client.advertiserId);
             } else {
-                gattAdvertiseNative(client.clientIf, false);
+                gattAdvertiseNative(client.advertiserId, false);
                 try {
                     mService.onAdvertiseInstanceDisabled(
-                            AdvertiseCallback.ADVERTISE_SUCCESS, client.clientIf);
+                            AdvertiseCallback.ADVERTISE_SUCCESS, client.advertiserId);
                 } catch (RemoteException e) {
                     Log.d(TAG, "failed onAdvertiseInstanceDisabled", e);
                 }
@@ -347,7 +357,7 @@ class AdvertiseManager {
         }
 
         private void enableAdvertising(AdvertiseClient client) {
-            int clientIf = client.clientIf;
+            int advertiserId = client.advertiserId;
             int minAdvertiseUnit = (int) getAdvertisingIntervalUnit(client.settings);
             int maxAdvertiseUnit = minAdvertiseUnit + ADVERTISING_INTERVAL_DELTA_UNIT;
             int advertiseEventType = getAdvertisingEventType(client);
@@ -356,14 +366,14 @@ class AdvertiseManager {
                     client.settings.getTimeout());
             if (mAdapterService.isMultiAdvertisementSupported()) {
                 gattClientEnableAdvNative(
-                        clientIf,
+                        advertiserId,
                         minAdvertiseUnit, maxAdvertiseUnit,
                         advertiseEventType,
                         ADVERTISING_CHANNEL_ALL,
                         txPowerLevel,
                         advertiseTimeoutSeconds);
             } else {
-                gattAdvertiseNative(client.clientIf, true);
+                gattAdvertiseNative(client.advertiserId, true);
             }
         }
 
@@ -395,11 +405,11 @@ class AdvertiseManager {
                 serviceUuids = advertisingUuidBytes.array();
             }
             if (mAdapterService.isMultiAdvertisementSupported()) {
-                gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+                gattClientSetAdvDataNative(client.advertiserId, isScanResponse, includeName,
                         includeTxPower, appearance,
                         manufacturerData, serviceData, serviceUuids);
             } else {
-                gattSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+                gattSetAdvDataNative(client.advertiserId, isScanResponse, includeName,
                         includeTxPower, 0, 0, appearance,
                         manufacturerData, serviceData, serviceUuids);
             }
@@ -488,25 +498,31 @@ class AdvertiseManager {
         }
 
         // Native functions
-        private native void gattClientDisableAdvNative(int client_if);
 
-        private native void gattClientEnableAdvNative(int client_if,
+        private native void registerAdvertiserNative(long app_uuid_lsb,
+                                                     long app_uuid_msb);
+
+        private native void unregisterAdvertiserNative(int advertiserId);
+
+        private native void gattClientDisableAdvNative(int advertiserId);
+
+        private native void gattClientEnableAdvNative(int advertiserId,
                 int min_interval, int max_interval, int adv_type, int chnl_map,
                 int tx_power, int timeout_s);
 
-        private native void gattClientUpdateAdvNative(int client_if,
+        private native void gattClientUpdateAdvNative(int advertiserId,
                 int min_interval, int max_interval, int adv_type, int chnl_map,
                 int tx_power, int timeout_s);
 
-        private native void gattClientSetAdvDataNative(int client_if,
+        private native void gattClientSetAdvDataNative(int advertiserId,
                 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,
+        private native void gattSetAdvDataNative(int advertiserId, 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 native void gattAdvertiseNative(int advertiserId, boolean start);
     }
 
     private void logd(String s) {
index c699967..3449dc4 100644 (file)
@@ -31,6 +31,7 @@ import android.bluetooth.IBluetoothGattServerCallback;
 import android.bluetooth.le.AdvertiseCallback;
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.IAdvertiserCallback;
 import android.bluetooth.le.ResultStorageDescriptor;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanRecord;
@@ -100,9 +101,14 @@ public class GattService extends ProfileService {
     };
 
     /**
-     * List of our registered clients.
+     * List of our registered advertisers.
      */
+    class AdvertiserMap extends ContextMap<IAdvertiserCallback> {}
+    AdvertiserMap mAdvertiserMap = new AdvertiserMap();
 
+    /**
+     * List of our registered clients.
+     */
     class ClientMap extends ContextMap<IBluetoothGattCallback> {}
     ClientMap mClientMap = new ClientMap();
 
@@ -264,6 +270,23 @@ public class GattService extends ProfileService {
         }
     }
 
+    class AdvertiserDeathRecipient implements IBinder.DeathRecipient {
+        int mAppIf;
+
+        public AdvertiserDeathRecipient(int appIf) {
+            mAppIf = appIf;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DBG) Log.d(TAG, "Binder is dead - unregistering advertiser (" + mAppIf + ")!");
+
+            AdvertiseClient client = new AdvertiseClient(mAppIf);
+            client.appDied = true;
+            stopMultiAdvertising(client);
+        }
+    }
+
     class ServerDeathRecipient implements IBinder.DeathRecipient {
         int mAppIf;
 
@@ -483,19 +506,31 @@ public class GattService extends ProfileService {
             service.sendNotification(serverIf, address, handle, confirm, value);
         }
 
+        public void registerAdvertiser(IAdvertiserCallback callback) {
+            GattService service = getService();
+            if (service == null) return;
+            service.registerAdvertiser(callback);
+        }
+
+        public void unregisterAdvertiser(int advertiserId) {
+            GattService service = getService();
+            if (service == null) return;
+            service.unregisterAdvertiser(advertiserId);
+        }
+
         @Override
-        public void startMultiAdvertising(int clientIf, AdvertiseData advertiseData,
+        public void startMultiAdvertising(int advertiserId, AdvertiseData advertiseData,
                 AdvertiseData scanResponse, AdvertiseSettings settings) {
             GattService service = getService();
             if (service == null) return;
-            service.startMultiAdvertising(clientIf, advertiseData, scanResponse, settings);
+            service.startMultiAdvertising(advertiserId, advertiseData, scanResponse, settings);
         }
 
         @Override
-        public void stopMultiAdvertising(int clientIf) {
+        public void stopMultiAdvertising(int advertiserId) {
             GattService service = getService();
             if (service == null) return;
-            service.stopMultiAdvertising(new AdvertiseClient(clientIf));
+            service.stopMultiAdvertising(new AdvertiseClient(advertiserId));
         }
 
         @Override
@@ -1071,13 +1106,15 @@ public class GattService extends ProfileService {
     }
 
     // callback from AdvertiseManager for advertise status dispatch.
-    void onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart,
+    void onMultipleAdvertiseCallback(int advertiserId, int status, boolean isStart,
             AdvertiseSettings settings) throws RemoteException {
-        ClientMap.App app = mClientMap.getById(clientIf);
+        AdvertiserMap.App app = mAdvertiserMap.getById(advertiserId);
         if (app == null || app.callback == null) {
             Log.e(TAG, "Advertise app or callback is null");
             return;
         }
+        if (DBG) Log.d(TAG, "onMultipleAdvertiseCallback : advertiserId: " + advertiserId
+            + " isStart: " + isStart + " status: " + status);
         app.callback.onMultiAdvertiseCallback(status, isStart, settings);
     }
 
@@ -1104,44 +1141,63 @@ 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);
+    void onAdvertiseCallback(int status, int advertiserId) {
+        if (DBG) Log.d(TAG, "onAdvertiseCallback,- advertiserId=" + advertiserId + ", status=" + status);
+        mAdvertiseManager.callbackDone(advertiserId, status);
     }
 
     // Followings are callbacks for Bluetooth LE Advertise operations.
     // Start advertising flow is
+    //     register advertiser         -> onAdvertiserRegistered
     //     enable advertising instance -> onAdvertiseInstaceEnabled
     // ->  set advertise data          -> onAdvertiseDataSet
     // ->  set scan response           -> onAdvertiseDataSet
 
+    void onAdvertiserRegistered(int status, int advertiserId, long uuidLsb, long uuidMsb)
+            throws RemoteException {
+        UUID uuid = new UUID(uuidMsb, uuidLsb);
+        if (DBG) Log.d(TAG, "onAdvertiserRegistered() - UUID=" + uuid
+                + ", advertiserId=" + advertiserId + ", status=" + status);
+
+        AdvertiserMap.App app = mAdvertiserMap.getByUuid(uuid);
+        if (app != null) {
+            if (status == 0) {
+                app.id = advertiserId;
+                app.linkToDeath(new AdvertiserDeathRecipient(advertiserId));
+            } else {
+                mAdvertiserMap.remove(advertiserId);
+            }
+            app.callback.onAdvertiserRegistered(status, advertiserId);
+        }
+    }
+
     // Callback when advertise instance is enabled.
-    void onAdvertiseInstanceEnabled(int status, int clientIf) {
+    void onAdvertiseInstanceEnabled(int status, int advertiserId) {
         if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - "
-                + "clientIf=" + clientIf + ", status=" + status);
-        mAdvertiseManager.callbackDone(clientIf, status);
+                + "advertiserId=" + advertiserId + ", status=" + status);
+        mAdvertiseManager.callbackDone(advertiserId, status);
     }
 
     // Not really used.
-    void onAdvertiseDataUpdated(int status, int client_if) {
-        if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - client_if=" + client_if
+    void onAdvertiseDataUpdated(int status, int advertiserId) {
+        if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - advertiserId=" + advertiserId
             + ", status=" + status);
     }
 
     // Callback when advertise data or scan response is set.
-    void onAdvertiseDataSet(int status, int clientIf) {
-        if (DBG) Log.d(TAG, "onAdvertiseDataSet() - clientIf=" + clientIf
+    void onAdvertiseDataSet(int status, int advertiserId) {
+        if (DBG) Log.d(TAG, "onAdvertiseDataSet() - advertiserId=" + advertiserId
             + ", status=" + status);
-        mAdvertiseManager.callbackDone(clientIf, status);
+        mAdvertiseManager.callbackDone(advertiserId, status);
     }
 
     // Callback when advertise instance is disabled
-    void onAdvertiseInstanceDisabled(int status, int clientIf) throws RemoteException {
-        if (DBG) Log.d(TAG, "onAdvertiseInstanceDisabled() - clientIf=" + clientIf
+    void onAdvertiseInstanceDisabled(int status, int advertiserId) throws RemoteException {
+        if (DBG) Log.d(TAG, "onAdvertiseInstanceDisabled() - advertiserId=" + advertiserId
             + ", status=" + status);
-        ClientMap.App app = mClientMap.getById(clientIf);
+        AdvertiserMap.App app = mAdvertiserMap.getById(advertiserId);
         if (app != null) {
-            Log.d(TAG, "Client app is not null!");
+            Log.d(TAG, "Advertiser app is not null!");
             boolean isStart = false;
             if (status == 0) {
                 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS,
@@ -1301,6 +1357,43 @@ public class GattService extends ProfileService {
     }
 
     /**************************************************************************
+     * ADVERTISER
+     *************************************************************************/
+
+    void registerAdvertiser(IAdvertiserCallback callback) {
+        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+
+        UUID uuid = UUID.randomUUID();
+        if (DBG) Log.d(TAG, "registerAdvertiser() - UUID=" + uuid);
+        mAdvertiserMap.add(uuid, callback, this);
+        mAdvertiseManager.registerAdvertiser(uuid);
+    }
+
+    void unregisterAdvertiser(int advertiserId) {
+        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+
+        if (DBG) Log.d(TAG, "unregisterAdvertiser() - advertiserId=" + advertiserId);
+        mAdvertiserMap.remove(advertiserId);
+        mAdvertiseManager.unregisterAdvertiser(advertiserId);
+    }
+
+    void startMultiAdvertising(int advertiserId, AdvertiseData advertiseData,
+            AdvertiseData scanResponse, AdvertiseSettings settings) {
+        enforceAdminPermission();
+
+        if (DBG) Log.d(TAG, "startMultiAdvertising() - advertiserId=" + advertiserId);
+        mAdvertiseManager.startAdvertising(new AdvertiseClient(advertiserId, settings, advertiseData,
+                scanResponse));
+    }
+
+    void stopMultiAdvertising(AdvertiseClient client) {
+        enforceAdminPermission();
+
+        if (DBG) Log.d(TAG, "stopMultiAdvertising() - advertiserId=" + client.advertiserId);
+        mAdvertiseManager.stopAdvertising(client);
+    }
+
+    /**************************************************************************
      * GATT Service functions - CLIENT
      *************************************************************************/
 
@@ -1337,18 +1430,6 @@ public class GattService extends ProfileService {
         gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0);
     }
 
-    void startMultiAdvertising(int clientIf, AdvertiseData advertiseData,
-            AdvertiseData scanResponse, AdvertiseSettings settings) {
-        enforceAdminPermission();
-        mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData,
-                scanResponse));
-    }
-
-    void stopMultiAdvertising(AdvertiseClient client) {
-        enforceAdminPermission();
-        mAdvertiseManager.stopAdvertising(client);
-    }
-
     int numHwTrackFiltersAvailable() {
         return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements()
                     - mScanManager.getCurrentUsedTrackingAdvertisement());