Create SettingManager class

This class helps give us a space to initialize settings to enabled
during boot (a bug in the code meant only the first setting was set to
enabled).

Bug: 217365200
Test: atest --host chre_simulation_tests
Merged-In: I987c8f86f3f49ef70071b3c3cddfa74958453370
Change-Id: I987c8f86f3f49ef70071b3c3cddfa74958453370
diff --git a/core/audio_request_manager.cc b/core/audio_request_manager.cc
index 6c5c5ee..db3edca 100644
--- a/core/audio_request_manager.cc
+++ b/core/audio_request_manager.cc
@@ -206,7 +206,8 @@
   }
 
   if (success &&
-      (getSettingState(Setting::MICROPHONE) != SettingState::DISABLED)) {
+      (EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+           Setting::MICROPHONE) != SettingState::DISABLED)) {
     scheduleNextAudioDataEvent(handle);
     updatePlatformHandleEnabled(handle, lastNumRequests);
   }
@@ -257,7 +258,8 @@
 
   if (success) {
     bool suspended =
-        (getSettingState(Setting::MICROPHONE) == SettingState::DISABLED);
+        (EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+             Setting::MICROPHONE) == SettingState::DISABLED);
     postAudioSamplingChangeEvent(instanceId, handle, requestList.available,
                                  suspended);
   }
@@ -347,7 +349,9 @@
   if (handle < mAudioRequestLists.size()) {
     if (mAudioRequestLists[handle].available != available) {
       bool suspended =
-          (getSettingState(Setting::MICROPHONE) == SettingState::DISABLED);
+          (EventLoopManagerSingleton::get()
+               ->getSettingManager()
+               .getSettingState(Setting::MICROPHONE) == SettingState::DISABLED);
       mAudioRequestLists[handle].available = available;
       postAudioSamplingChangeEvents(handle, suspended);
     }
@@ -359,7 +363,8 @@
 }
 
 void AudioRequestManager::scheduleNextAudioDataEvent(uint32_t handle) {
-  if (getSettingState(Setting::MICROPHONE) == SettingState::DISABLED) {
+  if (EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+          Setting::MICROPHONE) == SettingState::DISABLED) {
     LOGD("Mic access disabled, doing nothing");
     return;
   }
diff --git a/core/debug_dump_manager.cc b/core/debug_dump_manager.cc
index a82478b..a2a5d4a 100644
--- a/core/debug_dump_manager.cc
+++ b/core/debug_dump_manager.cc
@@ -89,7 +89,7 @@
 #ifdef CHRE_AUDIO_SUPPORT_ENABLED
   eventLoopManager->getAudioRequestManager().logStateToBuffer(mDebugDump);
 #endif  // CHRE_AUDIO_SUPPORT_ENABLED
-  logSettingStateToBuffer(mDebugDump);
+  eventLoopManager->getSettingManager().logStateToBuffer(mDebugDump);
   logStateToBuffer(mDebugDump);
 }
 
diff --git a/core/gnss_manager.cc b/core/gnss_manager.cc
index 32d8494..905de17 100644
--- a/core/gnss_manager.cc
+++ b/core/gnss_manager.cc
@@ -265,7 +265,8 @@
     uint16_t reportEventType;
     if (!getReportEventType(static_cast<SystemCallbackType>(type),
                             &reportEventType) ||
-        (getSettingState(Setting::LOCATION) == SettingState::DISABLED)) {
+        (EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+             Setting::LOCATION) == SettingState::DISABLED)) {
       freeReportEventCallback(reportEventType, data);
     } else {
       EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
@@ -295,7 +296,9 @@
 }
 
 bool GnssSession::updatePlatformRequest(bool forceUpdate) {
-  SettingState locationSetting = getSettingState(Setting::LOCATION);
+  SettingState locationSetting =
+      EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+          Setting::LOCATION);
 
   bool desiredPlatformState =
       (locationSetting == SettingState::ENABLED) && !mRequests.empty();
@@ -379,7 +382,8 @@
   } else if (stateTransitionIsRequired(enable, minInterval, hasRequest,
                                        requestIndex)) {
     if (enable &&
-        getSettingState(Setting::LOCATION) == SettingState::DISABLED) {
+        EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+            Setting::LOCATION) == SettingState::DISABLED) {
       // Treat as success but post async failure per API.
       success = postAsyncResultEvent(instanceId, false /* success */, enable,
                                      minInterval, CHRE_ERROR_FUNCTION_DISABLED,
@@ -680,7 +684,8 @@
     if (stateTransitionIsRequired(stateTransition.enable,
                                   stateTransition.minInterval, hasRequest,
                                   requestIndex)) {
-      if (getSettingState(Setting::LOCATION) == SettingState::DISABLED) {
+      if (EventLoopManagerSingleton::get()->getSettingManager().getSettingState(
+              Setting::LOCATION) == SettingState::DISABLED) {
         postAsyncResultEventFatal(
             stateTransition.nanoappInstanceId, false /* success */,
             stateTransition.enable, stateTransition.minInterval,
diff --git a/core/include/chre/core/event_loop_manager.h b/core/include/chre/core/event_loop_manager.h
index 1b7e46c..199dd5b 100644
--- a/core/include/chre/core/event_loop_manager.h
+++ b/core/include/chre/core/event_loop_manager.h
@@ -21,6 +21,7 @@
 #include "chre/core/event_loop.h"
 #include "chre/core/event_loop_common.h"
 #include "chre/core/host_comms_manager.h"
+#include "chre/core/settings.h"
 #include "chre/platform/memory_manager.h"
 #include "chre/platform/mutex.h"
 #include "chre/util/always_false.h"
@@ -290,6 +291,13 @@
   }
 
   /**
+   * @return A reference to the setting manager.
+   */
+  SettingManager &getSettingManager() {
+    return mSettingManager;
+  }
+
+  /**
    * Performs second-stage initialization of things that are not necessarily
    * required at construction time but need to be completed prior to executing
    * any nanoapps.
@@ -342,6 +350,9 @@
 
   //! The DebugDumpManager that handles the debug dump process.
   DebugDumpManager mDebugDumpManager;
+
+  //! The SettingManager that manages setting states.
+  SettingManager mSettingManager;
 };
 
 //! Provide an alias to the EventLoopManager singleton.
diff --git a/core/include/chre/core/settings.h b/core/include/chre/core/settings.h
index 5c8683e..63e4743 100644
--- a/core/include/chre/core/settings.h
+++ b/core/include/chre/core/settings.h
@@ -34,42 +34,66 @@
 enum class SettingState : int8_t { UNKNOWN = -1, DISABLED = 0, ENABLED };
 
 /**
- * Updates the state of a given setting.
- *
- * @param setting The setting to update.
- * @param state The state of the setting.
+ * Stores latest setting state and is responsible for sending setting updates
+ * to nanoapps.
  */
-void postSettingChange(Setting setting, SettingState state);
+class SettingManager {
+ public:
+  SettingManager();
 
-/**
- * Gets the current state of a given setting. Must be called from the context of
- * the main CHRE thread.
- *
- * @param setting The setting to check the current state of.
- *
- * @return The current state of the setting, SETTING_STATE_UNKNOWN if the
- * provided setting is invalid.
- */
-SettingState getSettingState(Setting setting);
+  /**
+   * Updates the state of a given setting.
+   *
+   * @param setting The setting to update.
+   * @param state The state of the setting.
+   */
+  void postSettingChange(Setting setting, SettingState state);
 
-/**
- * Gets the current state of a given setting, but returns the state as an
- * int8_t. The state is guaranteed to be a member of enum chreUserSettingState.
- *
- * @param setting The setting to check the current state of (see
- * CHRE_USER_SETTINGS).
- *
- * @return The current state of the setting (see enum chreUserSettingState)
- */
-int8_t getSettingStateAsInt8(uint8_t setting);
+  /**
+   * Gets the current state of a given setting. Must be called from the context
+   * of the main CHRE thread.
+   *
+   * @param setting The setting to check the current state of.
+   *
+   * @return The current state of the setting, SETTING_STATE_UNKNOWN if the
+   * provided setting is invalid.
+   */
+  SettingState getSettingState(Setting setting);
 
-/**
- * Logs the settings related stats in the debug dump. Must be called from the
- * context of the main CHRE thread.
- *
- * @param debugDump The object that is printed into for debug dump logs.
- */
-void logSettingStateToBuffer(DebugDumpWrapper &debugDump);
+  /**
+   * Gets the current state of a given setting, but returns the state as an
+   * int8_t. The state is guaranteed to be a member of enum
+   * chreUserSettingState.
+   *
+   * @param setting The setting to check the current state of (see
+   * CHRE_USER_SETTINGS).
+   *
+   * @return The current state of the setting (see enum chreUserSettingState)
+   */
+  int8_t getSettingStateAsInt8(uint8_t setting);
+
+  /**
+   * Logs the settings related stats in the debug dump. Must be called from the
+   * context of the main CHRE thread.
+   *
+   * @param debugDump The object that is printed into for debug dump logs.
+   */
+  void logStateToBuffer(DebugDumpWrapper &debugDump);
+
+ private:
+  static constexpr size_t kNumSettings =
+      static_cast<size_t>(Setting::SETTING_MAX);
+
+  //! The current state for each setting.
+  SettingState mSettingStateList[kNumSettings];
+
+  void setSettingState(Setting setting, SettingState state);
+
+  const char *getSettingStateString(Setting setting);
+
+  static void settingChangedCallback(uint16_t type, void *data,
+                                     void *extraData);
+};
 
 }  // namespace chre
 
diff --git a/core/settings.cc b/core/settings.cc
index dc3786d..d1494d1 100644
--- a/core/settings.cc
+++ b/core/settings.cc
@@ -20,6 +20,7 @@
 
 #include "chre/core/event_loop_manager.h"
 #include "chre/platform/log.h"
+#include "chre/util/macros.h"
 #include "chre/util/nested_data_ptr.h"
 
 #include "chre_api/chre/user_settings.h"
@@ -28,11 +29,6 @@
 
 namespace {
 
-constexpr size_t kNumSettings = static_cast<size_t>(Setting::SETTING_MAX);
-
-//! The current state for each setting.
-SettingState gSettingStateList[kNumSettings] = {SettingState::ENABLED};
-
 /**
  * @param setting The setting to get the index for.
  * @param index A non-null pointer to store the index.
@@ -48,30 +44,6 @@
   return false;
 }
 
-void setSettingState(Setting setting, SettingState state) {
-  size_t index;
-  if (!getIndexForSetting(setting, &index)) {
-    LOGE("Unknown setting %" PRId8, static_cast<int8_t>(setting));
-  } else {
-    gSettingStateList[index] = state;
-  }
-}
-
-const char *getSettingStateString(Setting setting) {
-  switch (getSettingState(setting)) {
-    case SettingState::ENABLED:
-      return "enabled";
-      break;
-    case SettingState::DISABLED:
-      return "disabled";
-      break;
-    default:
-      break;
-  }
-
-  return "unknown";
-}
-
 void sendSettingChangedNotification(Setting setting, SettingState state) {
   auto *eventData = memoryAlloc<struct chreUserSettingChangedEvent>();
   auto settingAsInt = static_cast<uint8_t>(setting);
@@ -88,11 +60,68 @@
   }
 }
 
-void settingChangedCallback(uint16_t /* type */, void *data, void *extraData) {
+}  // anonymous namespace
+
+SettingManager::SettingManager() {
+  // Default most settings to true until the host tells us otherwise so
+  // nanoapps can begin work during boot which will get canceled if the user has
+  // disabled the feature.
+  for (size_t i = 0; i < ARRAY_SIZE(mSettingStateList); ++i) {
+    mSettingStateList[i] = SettingState::ENABLED;
+  }
+
+  // Airplane mode should be disabled since it being enabled causes API usage
+  // restrictions.
+  auto airplaneIndex = static_cast<uint8_t>(Setting::AIRPLANE_MODE);
+  mSettingStateList[airplaneIndex] = SettingState::DISABLED;
+}
+
+void SettingManager::postSettingChange(Setting setting, SettingState state) {
+  LOGD("Posting setting change: setting type %" PRIu8 " state %" PRIu8,
+       static_cast<uint8_t>(setting), static_cast<uint8_t>(state));
+
+  EventLoopManagerSingleton::get()->deferCallback(
+      SystemCallbackType::SettingChangeEvent, NestedDataPtr<Setting>(setting),
+      settingChangedCallback, NestedDataPtr<SettingState>(state));
+}
+
+SettingState SettingManager::getSettingState(Setting setting) {
+  size_t index;
+  if (getIndexForSetting(setting, &index)) {
+    return mSettingStateList[index];
+  }
+
+  LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
+  return SettingState::UNKNOWN;
+}
+
+int8_t SettingManager::getSettingStateAsInt8(uint8_t setting) {
+  int8_t state = CHRE_USER_SETTING_STATE_UNKNOWN;
+  if (setting < static_cast<uint8_t>(Setting::SETTING_MAX)) {
+    auto settingEnum = static_cast<Setting>(setting);
+    state = static_cast<int8_t>(getSettingState(settingEnum));
+  }
+  return state;
+}
+
+void SettingManager::logStateToBuffer(DebugDumpWrapper &debugDump) {
+  debugDump.print("\nSettings:");
+  debugDump.print("\n Location %s", getSettingStateString(Setting::LOCATION));
+  debugDump.print("\n WiFi available %s",
+                  getSettingStateString(Setting::WIFI_AVAILABLE));
+  debugDump.print("\n Airplane mode %s",
+                  getSettingStateString(Setting::AIRPLANE_MODE));
+  debugDump.print("\n Microphone Access %s",
+                  getSettingStateString(Setting::MICROPHONE));
+}
+
+void SettingManager::settingChangedCallback(uint16_t /* type */, void *data,
+                                            void *extraData) {
   Setting setting = NestedDataPtr<Setting>(data);
   SettingState settingState = NestedDataPtr<SettingState>(extraData);
 
-  setSettingState(setting, settingState);
+  EventLoopManagerSingleton::get()->getSettingManager().setSettingState(
+      setting, settingState);
 
   LOGD("Setting changed callback called for setting %u state %u",
        static_cast<uint8_t>(setting), static_cast<uint8_t>(settingState));
@@ -110,45 +139,28 @@
   sendSettingChangedNotification(setting, settingState);
 }
 
-}  // anonymous namespace
-
-void postSettingChange(Setting setting, SettingState state) {
-  LOGD("Posting setting change: setting type %" PRIu8 " state %" PRIu8,
-       static_cast<uint8_t>(setting), static_cast<uint8_t>(state));
-
-  EventLoopManagerSingleton::get()->deferCallback(
-      SystemCallbackType::SettingChangeEvent, NestedDataPtr<Setting>(setting),
-      settingChangedCallback, NestedDataPtr<SettingState>(state));
-}
-
-SettingState getSettingState(Setting setting) {
+void SettingManager::setSettingState(Setting setting, SettingState state) {
   size_t index;
-  if (getIndexForSetting(setting, &index)) {
-    return gSettingStateList[index];
+  if (!getIndexForSetting(setting, &index)) {
+    LOGE("Unknown setting %" PRId8, static_cast<int8_t>(setting));
+  } else {
+    mSettingStateList[index] = state;
   }
-
-  LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
-  return SettingState::UNKNOWN;
 }
 
-int8_t getSettingStateAsInt8(uint8_t setting) {
-  int8_t state = CHRE_USER_SETTING_STATE_UNKNOWN;
-  if (setting < static_cast<uint8_t>(Setting::SETTING_MAX)) {
-    auto settingEnum = static_cast<Setting>(setting);
-    state = static_cast<int8_t>(getSettingState(settingEnum));
+const char *SettingManager::getSettingStateString(Setting setting) {
+  switch (getSettingState(setting)) {
+    case SettingState::ENABLED:
+      return "enabled";
+      break;
+    case SettingState::DISABLED:
+      return "disabled";
+      break;
+    default:
+      break;
   }
-  return state;
-}
 
-void logSettingStateToBuffer(DebugDumpWrapper &debugDump) {
-  debugDump.print("\nSettings:");
-  debugDump.print("\n Location %s", getSettingStateString(Setting::LOCATION));
-  debugDump.print("\n WiFi available %s",
-                  getSettingStateString(Setting::WIFI_AVAILABLE));
-  debugDump.print("\n Airplane mode %s",
-                  getSettingStateString(Setting::AIRPLANE_MODE));
-  debugDump.print("\n Microphone Access %s",
-                  getSettingStateString(Setting::MICROPHONE));
+  return "unknown";
 }
 
 }  // namespace chre
diff --git a/platform/shared/chre_api_user_settings.cc b/platform/shared/chre_api_user_settings.cc
index d149688..76e1b29 100644
--- a/platform/shared/chre_api_user_settings.cc
+++ b/platform/shared/chre_api_user_settings.cc
@@ -26,7 +26,9 @@
 using chre::SettingState;
 
 DLL_EXPORT int8_t chreUserSettingGetState(uint8_t setting) {
-  return chre::getSettingStateAsInt8(setting);
+  return chre::EventLoopManagerSingleton::get()
+      ->getSettingManager()
+      .getSettingStateAsInt8(setting);
 }
 
 DLL_EXPORT void chreUserSettingConfigureEvents(uint8_t setting, bool enable) {
diff --git a/platform/slpi/host_link.cc b/platform/slpi/host_link.cc
index a8bdfec..956413c 100644
--- a/platform/slpi/host_link.cc
+++ b/platform/slpi/host_link.cc
@@ -944,7 +944,8 @@
   SettingState chreSettingState;
   if (HostProtocolChre::getSettingFromFbs(setting, &chreSetting) &&
       HostProtocolChre::getSettingStateFromFbs(state, &chreSettingState)) {
-    postSettingChange(chreSetting, chreSettingState);
+    EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
+        chreSetting, chreSettingState);
   }
 }