Handle host messages in CHRE settings test

Bug: 135951924
Test: Compile and load nanoapp using test app, verify host messages decoded
Change-Id: Ic61d08df2648beae3ebcd43f576a48fbc6d2aedf
diff --git a/apps/test/common/chre_settings_test/Makefile b/apps/test/common/chre_settings_test/Makefile
index d6bc5cd..3a95042 100644
--- a/apps/test/common/chre_settings_test/Makefile
+++ b/apps/test/common/chre_settings_test/Makefile
@@ -34,12 +34,18 @@
 # Source Code ##################################################################
 
 COMMON_SRCS += $(NANOAPP_PATH)/src/chre_settings_test.cc
+COMMON_SRCS += $(NANOAPP_PATH)/src/chre_settings_test_manager.cc
+COMMON_SRCS += $(NANOAPP_PATH)/src/chre_settings_test_util.cc
+COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/callbacks.cc
 
 # Compiler Flags ###############################################################
 
 # Defines
 COMMON_CFLAGS += -DNANOAPP_MINIMUM_LOG_LEVEL=CHRE_LOG_LEVEL_INFO
 
+# Includes
+COMMON_CFLAGS += -I$(NANOAPP_PATH)/inc
+
 # Makefile Includes ############################################################
 
 include $(CHRE_PREFIX)/build/nanoapp/app.mk
diff --git a/apps/test/common/chre_settings_test/inc/chre_settings_test_manager.h b/apps/test/common/chre_settings_test/inc/chre_settings_test_manager.h
new file mode 100644
index 0000000..f28c90d
--- /dev/null
+++ b/apps/test/common/chre_settings_test/inc/chre_settings_test_manager.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef CHRE_SETTINGS_TEST_MANAGER_H_
+#define CHRE_SETTINGS_TEST_MANAGER_H_
+
+#include "chre_settings_test.nanopb.h"
+
+#include <chre.h>
+#include <cinttypes>
+
+#include "chre/util/singleton.h"
+
+namespace chre {
+
+namespace settings_test {
+
+/**
+ * A class to manage a CHRE settings test session.
+ */
+class Manager {
+ public:
+  enum class Feature : uint8_t {
+    WIFI_SCANNING = 0,
+    WIFI_RTT,
+    GNSS_LOCATION,
+    GNSS_MEASUREMENT,
+    WWAN_CELL_INFO,
+  };
+
+  enum class FeatureState : uint8_t {
+    ENABLED = 0,
+    DISABLED,
+  };
+
+  /**
+   * Handles an event from CHRE. Semantics are the same as nanoappHandleEvent.
+   */
+  void handleEvent(uint32_t senderInstanceId, uint16_t eventType,
+                   const void *eventData);
+
+ private:
+  /**
+   * Handles a message from the host.
+   *
+   * @param senderInstanceId The sender instance ID of this message.
+   * @param hostData The data from the host.
+   */
+  void handleMessageFromHost(uint32_t senderInstanceId,
+                             const chreMessageFromHostData *hostData);
+
+  /**
+   * Initiates the test given a start command from the host.
+   *
+   * @param hostEndpointId The test host endpoint ID.
+   * @param feature The feature to test.
+   * @param state The feature state.
+   */
+  void handleStartTestMessage(uint16_t hostEndpointId, Feature feature,
+                              FeatureState state);
+
+  /**
+   * Processes data from CHRE.
+   *
+   * @param eventType The event type as defined by CHRE.
+   * @param eventData A pointer to the data.
+   */
+  void handleDataFromChre(uint16_t eventType, const void *eventData);
+};
+
+// The settings test manager singleton.
+typedef chre::Singleton<Manager> ManagerSingleton;
+
+}  // namespace settings_test
+
+}  // namespace chre
+
+#endif  // CHRE_SETTINGS_TEST_MANAGER_H_
diff --git a/apps/test/common/chre_settings_test/inc/chre_settings_test_util.h b/apps/test/common/chre_settings_test/inc/chre_settings_test_util.h
new file mode 100644
index 0000000..82a9c67
--- /dev/null
+++ b/apps/test/common/chre_settings_test/inc/chre_settings_test_util.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef CHRE_SETTINGS_TEST_UTIL_H_
+#define CHRE_SETTINGS_TEST_UTIL_H_
+
+#include <cinttypes>
+
+namespace chre {
+
+namespace settings_test {
+
+void sendTestResultToHost(uint16_t hostEndpointId, bool success);
+
+}  // namespace settings_test
+
+}  // namespace chre
+
+#endif  // CHRE_SETTINGS_TEST_UTIL_H_
diff --git a/apps/test/common/chre_settings_test/src/chre_settings_test.cc b/apps/test/common/chre_settings_test/src/chre_settings_test.cc
index 650bb72..e5104c4 100644
--- a/apps/test/common/chre_settings_test/src/chre_settings_test.cc
+++ b/apps/test/common/chre_settings_test/src/chre_settings_test.cc
@@ -15,16 +15,25 @@
  */
 
 #include <chre.h>
+#include <cinttypes>
+
+#include "chre_settings_test_manager.h"
 
 namespace chre {
 
 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
-                                   uint16_t eventType, const void *eventData) {}
+                                   uint16_t eventType, const void *eventData) {
+  settings_test::ManagerSingleton::get()->handleEvent(senderInstanceId,
+                                                      eventType, eventData);
+}
 
 extern "C" bool nanoappStart(void) {
+  settings_test::ManagerSingleton::init();
   return true;
 }
 
-extern "C" void nanoappEnd(void) {}
+extern "C" void nanoappEnd(void) {
+  settings_test::ManagerSingleton::deinit();
+}
 
 }  // namespace chre
diff --git a/apps/test/common/chre_settings_test/src/chre_settings_test_manager.cc b/apps/test/common/chre_settings_test/src/chre_settings_test_manager.cc
new file mode 100644
index 0000000..7ec3f47
--- /dev/null
+++ b/apps/test/common/chre_settings_test/src/chre_settings_test_manager.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 "chre_settings_test_manager.h"
+
+#include <pb_decode.h>
+
+#include "chre/util/nanoapp/log.h"
+#include "chre_settings_test.nanopb.h"
+#include "chre_settings_test_util.h"
+
+#define LOG_TAG "ChreSettingsTest"
+
+namespace chre {
+
+namespace settings_test {
+
+namespace {
+
+bool getFeature(const chre_settings_test_TestCommand &command,
+                Manager::Feature *feature) {
+  bool success = true;
+  switch (command.feature) {
+    case chre_settings_test_TestCommand_Feature_WIFI_SCANNING:
+      *feature = Manager::Feature::WIFI_SCANNING;
+      break;
+    case chre_settings_test_TestCommand_Feature_WIFI_RTT:
+      *feature = Manager::Feature::WIFI_RTT;
+      break;
+    case chre_settings_test_TestCommand_Feature_GNSS_LOCATION:
+      *feature = Manager::Feature::GNSS_LOCATION;
+      break;
+    case chre_settings_test_TestCommand_Feature_GNSS_MEASUREMENT:
+      *feature = Manager::Feature::GNSS_MEASUREMENT;
+      break;
+    case chre_settings_test_TestCommand_Feature_WWAN_CELL_INFO:
+      *feature = Manager::Feature::WWAN_CELL_INFO;
+      break;
+    default:
+      LOGE("Unknown feature %d", command.feature);
+      success = false;
+  }
+
+  return success;
+}
+
+bool getFeatureState(const chre_settings_test_TestCommand &command,
+                     Manager::FeatureState *state) {
+  bool success = true;
+  switch (command.state) {
+    case chre_settings_test_TestCommand_State_ENABLED:
+      *state = Manager::FeatureState::ENABLED;
+      break;
+    case chre_settings_test_TestCommand_State_DISABLED:
+      *state = Manager::FeatureState::DISABLED;
+      break;
+    default:
+      LOGE("Unknown feature state %d", command.state);
+      success = false;
+  }
+
+  return success;
+}
+
+}  // anonymous namespace
+
+void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
+                          const void *eventData) {
+  if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
+    handleMessageFromHost(
+        senderInstanceId,
+        static_cast<const chreMessageFromHostData *>(eventData));
+  } else if (senderInstanceId == CHRE_INSTANCE_ID) {
+    handleDataFromChre(eventType, eventData);
+  } else {
+    LOGW("Got unknown event type from senderInstanceId %" PRIu32
+         " and with eventType %" PRIu16,
+         senderInstanceId, eventType);
+  }
+}
+
+void Manager::handleMessageFromHost(uint32_t senderInstanceId,
+                                    const chreMessageFromHostData *hostData) {
+  bool success = false;
+  uint32_t messageType = hostData->messageType;
+  if (senderInstanceId != CHRE_INSTANCE_ID) {
+    LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
+  } else if (messageType != chre_settings_test_MessageType_TEST_COMMAND) {
+    LOGE("Invalid message type %" PRIu32, messageType);
+  } else {
+    pb_istream_t istream = pb_istream_from_buffer(
+        static_cast<const pb_byte_t *>(hostData->message),
+        hostData->messageSize);
+    chre_settings_test_TestCommand testCommand =
+        chre_settings_test_TestCommand_init_default;
+
+    if (!pb_decode(&istream, chre_settings_test_TestCommand_fields,
+                   &testCommand)) {
+      LOGE("Failed to decode start command error %s", PB_GET_ERROR(&istream));
+    } else {
+      Feature feature;
+      FeatureState state;
+      if (getFeature(testCommand, &feature) &&
+          getFeatureState(testCommand, &state)) {
+        handleStartTestMessage(hostData->hostEndpoint, feature, state);
+        success = true;
+      }
+    }
+  }
+
+  if (!success) {
+    sendTestResultToHost(hostData->hostEndpoint, false /* success */);
+  }
+}
+
+void Manager::handleStartTestMessage(uint16_t hostEndpointId, Feature feature,
+                                     FeatureState state) {
+  // TODO: Implement this
+}
+
+void Manager::handleDataFromChre(uint16_t eventType, const void *eventData) {
+  // TODO: Implement this
+}
+
+}  // namespace settings_test
+
+}  // namespace chre
diff --git a/apps/test/common/chre_settings_test/src/chre_settings_test_util.cc b/apps/test/common/chre_settings_test/src/chre_settings_test_util.cc
new file mode 100644
index 0000000..9b28bd8
--- /dev/null
+++ b/apps/test/common/chre_settings_test/src/chre_settings_test_util.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 <chre.h>
+#include <pb_encode.h>
+#include <cinttypes>
+
+#include "chre_settings_test.nanopb.h"
+#include "chre_settings_test_manager.h"
+
+#include "chre/util/nanoapp/callbacks.h"
+#include "chre/util/nanoapp/log.h"
+
+#define LOG_TAG "ChreSettingsTest"
+
+namespace chre {
+
+namespace settings_test {
+
+void sendTestResultToHost(uint16_t hostEndpointId, bool success) {
+  chre_settings_test_TestResult result =
+      chre_settings_test_TestResult_init_default;
+  result.has_code = true;
+  result.code = success ? chre_settings_test_TestResult_Code_PASSED
+                        : chre_settings_test_TestResult_Code_FAILED;
+  size_t size;
+  if (!pb_get_encoded_size(&size, chre_settings_test_TestResult_fields,
+                           &result)) {
+    LOGE("Failed to get message size");
+  } else {
+    pb_byte_t *bytes = static_cast<pb_byte_t *>(chreHeapAlloc(size));
+    if (bytes == nullptr) {
+      LOG_OOM();
+    } else {
+      pb_ostream_t stream = pb_ostream_from_buffer(bytes, size);
+      if (!pb_encode(&stream, chre_settings_test_TestResult_fields, &result)) {
+        LOGE("Failed to encode test result error %s", PB_GET_ERROR(&stream));
+        chreHeapFree(bytes);
+      } else {
+        chreSendMessageToHostEndpoint(
+            bytes, size, chre_settings_test_MessageType_TEST_RESULT,
+            hostEndpointId, heapFreeMessageCallback);
+      }
+    }
+  }
+}
+
+}  // namespace settings_test
+
+}  // namespace chre