service: Implement IBluetoothGattServer.addCharacteristic

Declared and implemented the IBluetoothGattServer.addCharacteristic
Binder API.

Bug: 24245347
Change-Id: I8baaed8d6dbf8ac2209b8fd0c918cade78dcba64
diff --git a/service/gatt_server.cpp b/service/gatt_server.cpp
index dd3cbd2..bb92b50 100644
--- a/service/gatt_server.cpp
+++ b/service/gatt_server.cpp
@@ -55,7 +55,7 @@
 
 std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration(
     const UUID& uuid, bool is_primary) {
-  VLOG(1) << __func__ << "server_if: " << server_if_
+  VLOG(1) << __func__ << " server_if: " << server_if_
           << " - UUID: " << uuid.ToString()
           << ", is_primary: " << is_primary;
   lock_guard<mutex> lock(mutex_);
@@ -86,16 +86,60 @@
   auto service_id = GattIdentifier::CreateServiceId(
       "", inst_id, uuid, is_primary);
 
+  // Pass 0 for permissions and properties as this is a service decl.
+  AttributeEntry entry(
+      *service_id, kCharacteristicPropertyNone, kAttributePermissionNone);
+
   pending_decl_.reset(new ServiceDeclaration());
   pending_decl_->num_handles++;  // 1 handle for the service decl. attribute
   pending_decl_->service_id = *service_id;
-  pending_decl_->attributes.push(*service_id);
+  pending_decl_->attributes.push_back(entry);
 
   return service_id;
 }
 
+std::unique_ptr<GattIdentifier> GattServer::AddCharacteristic(
+      const UUID& uuid, int properties, int permissions) {
+  VLOG(1) << __func__ << " server_if: " << server_if_
+          << " - UUID: " << uuid.ToString()
+          << ", properties: " << properties
+          << ", permissions: " << permissions;
+  lock_guard<mutex> lock(mutex_);
+
+  if (!pending_decl_) {
+    LOG(ERROR) << "Service declaration not begun";
+    return nullptr;
+  }
+
+  // Calculate the instance ID for this characteristic by searching through the
+  // pending entries.
+  int inst_id = 0;
+  for (const auto& entry : pending_decl_->attributes) {
+    const GattIdentifier* gatt_id = &entry.id;
+
+    if (!gatt_id->IsCharacteristic())
+      continue;
+
+    if (gatt_id->characteristic_uuid() == uuid)
+      ++inst_id;
+  }
+
+  CHECK(pending_decl_->service_id.IsService());
+
+  auto char_id = GattIdentifier::CreateCharacteristicId(
+      inst_id, uuid, pending_decl_->service_id);
+
+  AttributeEntry entry(*char_id, properties, permissions);
+
+  // 2 handles for the characteristic declaration and the value attributes.
+  pending_decl_->num_handles += 2;
+  pending_decl_->attributes.push_back(entry);
+
+  return char_id;
+}
+
 bool GattServer::EndServiceDeclaration(const ResultCallback& callback) {
-  VLOG(1) << __func__ << "server_if: " << server_if_;
+  VLOG(1) << __func__ << " server_if: " << server_if_;
   lock_guard<mutex> lock(mutex_);
 
   if (!callback) {
@@ -146,7 +190,7 @@
     hal::BluetoothGattInterface* gatt_iface,
     int status, int server_if,
     const btgatt_srvc_id_t& srvc_id,
-    int srvc_handle) {
+    int service_handle) {
   lock_guard<mutex> lock(mutex_);
 
   if (server_if != server_if_)
@@ -159,8 +203,9 @@
   CHECK(*gatt_id == pending_decl_->service_id);
   CHECK(pending_id_->IsService());
 
-  VLOG(1) << __func__ << " - server_if: " << server_if
-          << " handle: " << srvc_handle
+  VLOG(1) << __func__ << " - status: " << status
+          << " server_if: " << server_if
+          << " handle: " << service_handle
           << " UUID: " << gatt_id->service_uuid().ToString();
 
   if (status != BT_STATUS_SUCCESS) {
@@ -169,26 +214,50 @@
   }
 
   // Add this to the handle map.
-  pending_handle_map_[*gatt_id] = srvc_handle;
+  pending_handle_map_[*gatt_id] = service_handle;
   CHECK(-1 == pending_decl_->service_handle);
-  pending_decl_->service_handle = srvc_handle;
+  pending_decl_->service_handle = service_handle;
 
-  // More entries aren't supported yet.
-  CHECK(pending_decl_->attributes.empty());
+  HandleNextEntry(gatt_iface);
+}
 
-  bt_status_t start_status = gatt_iface->GetServerHALInterface()->start_service(
-      server_if_, srvc_handle, TRANSPORT_BREDR | TRANSPORT_LE);
-  if (start_status == BT_STATUS_SUCCESS)
-    return;  // Wait for the pending call.
+void GattServer::CharacteristicAddedCallback(
+    hal::BluetoothGattInterface* gatt_iface,
+    int status, int server_if,
+    const bt_uuid_t& uuid,
+    int service_handle,
+    int char_handle) {
+  lock_guard<mutex> lock(mutex_);
 
-  // Notify failure.
-  NotifyEndCallbackAndClearData(static_cast<BLEStatus>(start_status), *gatt_id);
+  if (server_if != server_if_)
+    return;
+
+  CHECK(pending_decl_);
+  CHECK(pending_decl_->service_handle == service_handle);
+  CHECK(pending_id_);
+  CHECK(pending_id_->IsCharacteristic());
+  CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
+
+  VLOG(1) << __func__ << " - status: " << status
+          << " server_if: " << server_if
+          << " service_handle: " << service_handle
+          << " char_handle: " << char_handle;
+
+  if (status != BT_STATUS_SUCCESS) {
+    NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
+                                  pending_decl_->service_id);
+    return;
+  }
+
+  // Add this to the handle map and continue.
+  pending_handle_map_[*pending_id_] = char_handle;
+  HandleNextEntry(gatt_iface);
 }
 
 void GattServer::ServiceStartedCallback(
     hal::BluetoothGattInterface* gatt_iface,
     int status, int server_if,
-    int srvc_handle) {
+    int service_handle) {
   lock_guard<mutex> lock(mutex_);
 
   if (server_if != server_if_)
@@ -196,16 +265,16 @@
 
   CHECK(pending_id_);
   CHECK(pending_decl_);
-  CHECK(pending_decl_->service_handle == srvc_handle);
+  CHECK(pending_decl_->service_handle == service_handle);
 
   VLOG(1) << __func__ << " - server_if: " << server_if
-          << " handle: " << srvc_handle;
+          << " handle: " << service_handle;
 
   // If we failed to start the service, remove it from the database and ignore
   // the result.
   if (status != BT_STATUS_SUCCESS) {
     gatt_iface->GetServerHALInterface()->delete_service(
-        server_if_, srvc_handle);
+        server_if_, service_handle);
   }
 
   // Complete the operation.
@@ -217,7 +286,7 @@
     hal::BluetoothGattInterface* /* gatt_iface */,
     int /* status */,
     int /* server_if */,
-    int /* srvc_handle */) {
+    int /* service_handle */) {
   // TODO(armansito): Support stopping a service.
 }
 
@@ -241,18 +310,72 @@
   pending_handle_map_.clear();
 }
 
-std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
+void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
+  CHECK(pending_decl_);
+  CHECK(gatt_iface);
+
+  auto next_entry = PopNextEntry();
+  if (!next_entry) {
+    // No more entries. Call start_service to finish up.
+    bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
+        server_if_,
+        pending_decl_->service_handle,
+        TRANSPORT_BREDR | TRANSPORT_LE);
+
+    // Terminate the procedure in the case of an error.
+    if (status != BT_STATUS_SUCCESS) {
+      NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
+                                    pending_decl_->service_id);
+    }
+
+    return;
+  }
+
+  if (next_entry->id.IsCharacteristic()) {
+    bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
+    bt_status_t status = gatt_iface->GetServerHALInterface()->
+        add_characteristic(
+            server_if_,
+            pending_decl_->service_handle,
+            &char_uuid,
+            next_entry->char_properties,
+            next_entry->permissions);
+
+    // Terminate the procedure in the case of an error.
+    if (status != BT_STATUS_SUCCESS) {
+      NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
+                                    pending_decl_->service_id);
+      return;
+    }
+
+    pending_id_.reset(new GattIdentifier(next_entry->id));
+
+    return;
+  }
+
+  NOTREACHED() << "Unexpected entry type";
+}
+
+std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
   CHECK(pending_decl_);
 
   if (pending_decl_->attributes.empty())
     return nullptr;
 
-  const GattIdentifier& next = pending_decl_->attributes.front();
-  std::unique_ptr<GattIdentifier> id(new GattIdentifier(next));
+  const auto& next = pending_decl_->attributes.front();
+  std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
 
-  pending_decl_->attributes.pop();
+  pending_decl_->attributes.pop_front();
 
-  return id;
+  return entry;
+}
+
+std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
+  auto entry = PopNextEntry();
+  if (!entry)
+    return nullptr;
+
+  return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
 }
 
 // GattServerFactory implementation