Adds BLE tests to bdtest.

Change-Id: Idcdc01339f0e8a14b6fedf27545566e7efdf53c2
diff --git a/system/test/suite/Android.mk b/system/test/suite/Android.mk
index 4ab021f..3caec79 100644
--- a/system/test/suite/Android.mk
+++ b/system/test/suite/Android.mk
@@ -27,10 +27,12 @@
 LOCAL_SRC_FILES := \
     cases/adapter.c \
     cases/cases.c \
+    cases/gatt.c \
     cases/pan.c \
     cases/rfcomm.c \
     support/adapter.c \
     support/callbacks.c \
+    support/gatt.c \
     support/hal.c \
     support/pan.c \
     support/rfcomm.c \
diff --git a/system/test/suite/base.h b/system/test/suite/base.h
index 97963a5..0aa7979 100644
--- a/system/test/suite/base.h
+++ b/system/test/suite/base.h
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
 #include <hardware/bt_pan.h>
 #include <hardware/bt_sock.h>
 #include <hardware/hardware.h>
diff --git a/system/test/suite/cases/cases.c b/system/test/suite/cases/cases.c
index 9dfcb70..10f98a2 100644
--- a/system/test/suite/cases/cases.c
+++ b/system/test/suite/cases/cases.c
@@ -34,10 +34,13 @@
 TEST_CASE_DECL(pan_disconnect);
 TEST_CASE_DECL(pan_quick_reconnect);
 
+TEST_CASE_DECL(gatt_client_register);
+TEST_CASE_DECL(gatt_client_scan);
+
 // These are run with the Bluetooth adapter disabled.
 const test_case_t sanity_suite[] = {
   TEST_CASE(adapter_enable_disable),
-  TEST_CASE(adapter_repeated_enable_disable),
+  TEST_CASE(adapter_repeated_enable_disable)
 };
 
 // The normal test suite is run with the adapter enabled.
@@ -53,6 +56,9 @@
   TEST_CASE(pan_enable),
   TEST_CASE(pan_connect),
   TEST_CASE(pan_disconnect),
+
+  TEST_CASE(gatt_client_register),
+  TEST_CASE(gatt_client_scan)
 };
 
 const size_t sanity_suite_size = ARRAY_SIZE(sanity_suite);
diff --git a/system/test/suite/cases/gatt.c b/system/test/suite/cases/gatt.c
new file mode 100644
index 0000000..f7d8f35
--- /dev/null
+++ b/system/test/suite/cases/gatt.c
@@ -0,0 +1,42 @@
+#include <stdlib.h>
+#include <time.h>
+
+#include "base.h"
+#include "support/gatt.h"
+#include "support/callbacks.h"
+
+bt_uuid_t app_uuid;
+
+static void assign_random_app_uuid(bt_uuid_t *uuid) {
+  srand(time(NULL));
+  for (int i = 0; i < 16; ++i) {
+    uuid->uu[i] = (uint8_t) (rand() % 256);
+  }
+}
+
+bool gatt_client_register() {
+  TASSERT(gatt_interface != NULL, "Null GATT interface.");
+
+  // Registers gatt client.
+  assign_random_app_uuid(&app_uuid);
+  gatt_interface->client->register_client(&app_uuid);
+  CALL_AND_WAIT(gatt_interface->client->register_client(&app_uuid), btgattc_register_app_cb);
+  TASSERT(gatt_get_status() == BT_STATUS_SUCCESS, "Error registering GATT app callback.");
+
+  // Unregisters gatt client. No callback is expected.
+  gatt_interface->client->unregister_client(gatt_get_client_interface());
+
+  return true;
+}
+
+bool gatt_client_scan() {
+  TASSERT(gatt_interface != NULL, "Null GATT interface.");
+
+  // Starts BLE scan. NB: This test assumes there is a BLE beacon advertising nearby.
+  CALL_AND_WAIT(gatt_interface->client->scan(true), btgattc_scan_result_cb);
+
+  // Ends BLE scan. No callback is expected.
+  gatt_interface->client->scan(false);
+
+  return true;
+}
diff --git a/system/test/suite/main.c b/system/test/suite/main.c
index 233bf0c..24cb862 100644
--- a/system/test/suite/main.c
+++ b/system/test/suite/main.c
@@ -27,6 +27,7 @@
 #include "osi/include/config.h"
 #include "support/callbacks.h"
 #include "support/hal.h"
+#include "support/gatt.h"
 #include "support/pan.h"
 #include "support/rfcomm.h"
 
@@ -175,6 +176,11 @@
     return 3;
   }
 
+  if (!gatt_init()) {
+    printf("Unable to initialize GATT.\n");
+    return 4;
+  }
+
   watchdog_running = true;
   pthread_create(&watchdog_thread, NULL, watchdog_fn, NULL);
 
diff --git a/system/test/suite/support/callbacks.c b/system/test/suite/support/callbacks.c
index 9c5f083..bbec5d2 100644
--- a/system/test/suite/support/callbacks.c
+++ b/system/test/suite/support/callbacks.c
@@ -35,6 +35,40 @@
 void pan_connection_state_changed(btpan_connection_state_t state, bt_status_t error, const bt_bdaddr_t *bd_addr, int local_role, int remote_role);
 void pan_control_state_changed(btpan_control_state_t state, int local_role, bt_status_t error, const char *ifname);
 
+// GATT client callbacks
+void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid);
+void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data);
+void btgattc_open_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda);
+void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda);
+void btgattc_search_complete_cb(int conn_id, int status);
+void btgattc_search_result_cb(int conn_id, btgatt_srvc_id_t *srvc_id);
+void btgattc_get_characteristic_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int char_prop);
+void btgattc_get_descriptor_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id);
+void btgattc_get_included_service_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_srvc_id_t *incl_srvc_id);
+void btgattc_register_for_notification_cb(int conn_id, int registered, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id);
+void btgattc_notify_cb(int conn_id, btgatt_notify_params_t *p_data);
+void btgattc_read_characteristic_cb(int conn_id, int status, btgatt_read_params_t *p_data);
+void btgattc_write_characteristic_cb(int conn_id, int status, btgatt_write_params_t *p_data);
+void btgattc_execute_write_cb(int conn_id, int status);
+void btgattc_read_descriptor_cb(int conn_id, int status, btgatt_read_params_t *p_data);
+void btgattc_write_descriptor_cb(int conn_id, int status, btgatt_write_params_t *p_data);
+void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status);
+void btgattc_advertise_cb(int status, int client_if);
+
+// GATT server callbacks
+void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid);
+void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda);
+void btgatts_service_added_cb(int status, int server_if, btgatt_srvc_id_t *srvc_id, int srvc_handle);
+void btgatts_included_service_added_cb(int status, int server_if, int srvc_handle, int incl_srvc_handle);
+void btgatts_characteristic_added_cb(int status, int server_if, bt_uuid_t *char_id, int srvc_handle, int char_handle);
+void btgatts_descriptor_added_cb(int status, int server_if, bt_uuid_t *descr_id, int srvc_handle, int descr_handle);
+void btgatts_service_started_cb(int status, int server_if, int srvc_handle);
+void btgatts_service_stopped_cb(int status, int server_if, int srvc_handle);
+void btgatts_service_deleted_cb(int status, int server_if, int srvc_handle);
+void btgatts_request_read_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int attr_handle, int offset, bool is_long);
+void btgatts_request_write_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value);
+void btgatts_request_exec_write_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int exec_write);
+void btgatts_response_confirmation_cb(int status, int handle);
 
 static struct {
   const char *name;
@@ -57,6 +91,48 @@
   // PAN callbacks
   { "pan_control_state_changed" },
   { "pan_connection_state_changed" },
+
+  // GATT client callbacks
+  { "btgattc_register_app_cb" },
+  { "btgattc_scan_result_cb" },
+  { "btgattc_open_cb" },
+  { "btgattc_close_cb" },
+  { "btgattc_search_complete_cb" },
+  { "btgattc_search_result_cb" },
+  { "btgattc_get_characteristic_cb" },
+  { "btgattc_get_descriptor_cb" },
+  { "btgattc_get_included_service_cb" },
+  { "btgattc_register_for_notification_cb" },
+  { "btgattc_notify_cb" },
+  { "btgattc_read_characteristic_cb" },
+  { "btgattc_write_characteristic_cb" },
+  { "btgattc_execute_write_cb" },
+  { "btgattc_read_descriptor_cb" },
+  { "btgattc_write_descriptor_cb" },
+  { "btgattc_remote_rssi_cb" },
+  { "btgattc_advertise_cb" },
+  {},
+  {},
+  {},
+  {},
+  {},
+  {},
+
+  // GATT server callbacks
+  { "btgatts_register_app_cb" },
+  { "btgatts_connection_cb" },
+  { "btgatts_service_added_cb" },
+  { "btgatts_included_service_added_cb" },
+  { "btgatts_characteristic_added_cb" },
+  { "btgatts_descriptor_added_cb" },
+  { "btgatts_service_started_cb" },
+  { "btgatts_service_stopped_cb" },
+  { "btgatts_service_deleted_cb" },
+  { "btgatts_request_read_cb" },
+  { "btgatts_request_write_cb" },
+  { "btgatts_request_exec_write_cb" },
+  { "btgatts_response_confirmation_cb" },
+
 };
 
 static bt_callbacks_t bt_callbacks = {
@@ -82,6 +158,55 @@
   pan_connection_state_changed,  // btpan_connection_state_callback
 };
 
+static const btgatt_client_callbacks_t gatt_client_callbacks = {
+  btgattc_register_app_cb,
+  btgattc_scan_result_cb,
+  btgattc_open_cb,
+  btgattc_close_cb,
+  btgattc_search_complete_cb,
+  btgattc_search_result_cb,
+  btgattc_get_characteristic_cb,
+  btgattc_get_descriptor_cb,
+  btgattc_get_included_service_cb,
+  btgattc_register_for_notification_cb,
+  btgattc_notify_cb,
+  btgattc_read_characteristic_cb,
+  btgattc_write_characteristic_cb,
+  btgattc_read_descriptor_cb,
+  btgattc_write_descriptor_cb,
+  btgattc_execute_write_cb,
+  btgattc_remote_rssi_cb,
+  btgattc_advertise_cb,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static const btgatt_server_callbacks_t gatt_server_callbacks = {
+  btgatts_register_app_cb,
+  btgatts_connection_cb,
+  btgatts_service_added_cb,
+  btgatts_included_service_added_cb,
+  btgatts_characteristic_added_cb,
+  btgatts_descriptor_added_cb,
+  btgatts_service_started_cb,
+  btgatts_service_stopped_cb,
+  btgatts_service_deleted_cb,
+  btgatts_request_read_cb,
+  btgatts_request_write_cb,
+  btgatts_request_exec_write_cb,
+  btgatts_response_confirmation_cb
+};
+
+static btgatt_callbacks_t gatt_callbacks = {
+  sizeof(btgatt_callbacks_t),
+  &gatt_client_callbacks,
+  &gatt_server_callbacks
+};
+
 void callbacks_init() {
   for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
     sem_init(&callback_data[i].semaphore, 0, 0);
@@ -102,6 +227,10 @@
   return &pan_callbacks;
 }
 
+btgatt_callbacks_t *callbacks_get_gatt_struct() {
+  return &gatt_callbacks;
+}
+
 sem_t *callbacks_get_semaphore(const char *name) {
   for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
     if (callback_data[i].name && !strcmp(name, callback_data[i].name)) {
diff --git a/system/test/suite/support/callbacks.h b/system/test/suite/support/callbacks.h
index 102e13f..e01de39 100644
--- a/system/test/suite/support/callbacks.h
+++ b/system/test/suite/support/callbacks.h
@@ -49,4 +49,5 @@
 
 bt_callbacks_t *callbacks_get_adapter_struct();
 btpan_callbacks_t *callbacks_get_pan_struct();
+btgatt_callbacks_t *callbacks_get_gatt_struct();
 sem_t *callbacks_get_semaphore(const char *name);
diff --git a/system/test/suite/support/gatt.c b/system/test/suite/support/gatt.c
new file mode 100644
index 0000000..3538b74
--- /dev/null
+++ b/system/test/suite/support/gatt.c
@@ -0,0 +1,167 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "base.h"
+#include "btcore/include/bdaddr.h"
+#include "support/callbacks.h"
+#include "support/gatt.h"
+
+const btgatt_interface_t *gatt_interface;
+static int gatt_client_interface;
+static int gatt_status;
+
+bool gatt_init() {
+  gatt_interface = bt_interface->get_profile_interface(BT_PROFILE_GATT_ID);
+  return gatt_interface->init(callbacks_get_gatt_struct()) == BT_STATUS_SUCCESS;
+}
+
+int gatt_get_client_interface() {
+  return gatt_client_interface;
+}
+
+int gatt_get_status() {
+  return gatt_status;
+}
+
+// GATT client callbacks
+void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid) {
+  gatt_status = status;
+  gatt_client_interface = clientIf;
+  CALLBACK_RET();
+}
+
+void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_open_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda) {
+  CALLBACK_RET();
+}
+
+void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda) {
+  CALLBACK_RET();
+}
+
+void btgattc_search_complete_cb(int conn_id, int status) {
+  CALLBACK_RET();
+}
+
+void btgattc_search_result_cb(int conn_id, btgatt_srvc_id_t *srvc_id) {
+  CALLBACK_RET();
+}
+
+void btgattc_get_characteristic_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int char_prop) {
+  CALLBACK_RET();
+}
+
+void btgattc_get_descriptor_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id) {
+  CALLBACK_RET();
+}
+
+void btgattc_get_included_service_cb(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_srvc_id_t *incl_srvc_id) {
+  CALLBACK_RET();
+}
+
+void btgattc_register_for_notification_cb(int conn_id, int registered, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id) {
+  CALLBACK_RET();
+}
+
+void btgattc_notify_cb(int conn_id, btgatt_notify_params_t *p_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_read_characteristic_cb(int conn_id, int status, btgatt_read_params_t *p_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_write_characteristic_cb(int conn_id, int status, btgatt_write_params_t *p_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_execute_write_cb(int conn_id, int status) {
+  CALLBACK_RET();
+}
+
+void btgattc_read_descriptor_cb(int conn_id, int status, btgatt_read_params_t *p_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_write_descriptor_cb(int conn_id, int status, btgatt_write_params_t *p_data) {
+  CALLBACK_RET();
+}
+
+void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status) {
+  CALLBACK_RET();
+}
+
+void btgattc_advertise_cb(int status, int client_if) {
+  CALLBACK_RET();
+}
+
+// GATT server callbacks
+void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid) {
+  CALLBACK_RET();
+}
+
+void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda) {
+  CALLBACK_RET();
+}
+
+void btgatts_service_added_cb(int status, int server_if, btgatt_srvc_id_t *srvc_id, int srvc_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_included_service_added_cb(int status, int server_if, int srvc_handle, int incl_srvc_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_characteristic_added_cb(int status, int server_if, bt_uuid_t *char_id, int srvc_handle, int char_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_descriptor_added_cb(int status, int server_if, bt_uuid_t *descr_id, int srvc_handle, int descr_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_service_started_cb(int status, int server_if, int srvc_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_service_stopped_cb(int status, int server_if, int srvc_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_service_deleted_cb(int status, int server_if, int srvc_handle) {
+  CALLBACK_RET();
+}
+
+void btgatts_request_read_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int attr_handle, int offset, bool is_long) {
+  CALLBACK_RET();
+}
+
+void btgatts_request_write_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) {
+  CALLBACK_RET();
+}
+
+void btgatts_request_exec_write_cb(int conn_id, int trans_id, bt_bdaddr_t *bda, int exec_write) {
+  CALLBACK_RET();
+}
+
+void btgatts_response_confirmation_cb(int status, int handle) {
+  CALLBACK_RET();
+}
\ No newline at end of file
diff --git a/system/test/suite/support/gatt.h b/system/test/suite/support/gatt.h
new file mode 100644
index 0000000..e5a61f2
--- /dev/null
+++ b/system/test/suite/support/gatt.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+extern const btgatt_interface_t *gatt_interface;
+
+bool gatt_init();
+int gatt_get_client_interface();
+int gatt_get_status();
\ No newline at end of file